一、引言
在传统 C++ 编程中,内存泄漏是一个常见的问题。智能指针的引入极大地简化了资源管理,尤其在 C++11 以后,unique_ptr、shared_ptr 和 weak_ptr 被标准化并广泛应用于现代 C++ 项目中。
本文将全面讲解三种智能指针的使用场景、内部机制、常见陷阱,并通过图示和代码示例帮助读者构建对智能指针的系统性理解。
智能指针类型 | 所有权 | 引用计数 | 可拷贝性 | 自动释放 |
---|---|---|---|---|
unique_ptr | 唯一 | 否 | 否 | 是 |
shared_ptr | 共享 | 是 | 是 | 是 |
weak_ptr | 非拥有 | 是 | 是 | 否 |
cpp复制编辑#include<memory>
std::unique_ptr<int> ptr = std::make_unique<int>(10);
std::cout << *ptr << std::endl;
cpp复制编辑std::unique_ptr<int> ptr2 = std::move(ptr);
📌 图示(逻辑结构):
scss复制编辑ptr ───► [10]
(转移后)
ptr (null) ptr2 ───► [10]
cpp复制编辑structFileCloser {
voidoperator()(FILE* f)const { fclose(f); }
};
std::unique_ptr<FILE, FileCloser> file(fopen("data.txt", "r"));
cpp复制编辑std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::shared_ptr<int> p2 = p1; // 引用计数 +1
📌 引用计数图示:
scss复制编辑p1 ─────┐
│
p2 ─────┘────► [int=5] (use_count=2)
cpp复制编辑std::cout << p1.use_count(); // 引用计数
std::cout << p1.unique(); // 是否为唯一引用
cpp复制编辑structA;
structB;
structA {
std::shared_ptr<B> b;
};
structB {
std::shared_ptr<A> a;
};
👎 此时对象永不释放!
📌 引用计数环:
css复制编辑A ─► B ─► A ...
cpp复制编辑structB {
std::weak_ptr<A> a; // 不增加引用计数
};
cpp复制编辑if (auto shared_a = b->a.lock()) {
shared_a->doSomething();
}
cpp复制编辑std::vector<std::shared_ptr<MyObject>> objs;
objs.push_back(std::make_shared<MyObject>());
注意事项:
txt复制编辑shared_ptr
│
▼
ControlBlock ───► 引用计数(use_count)
└──► 弱引用计数(weak_count)
└──► 实际对象指针
cpp复制编辑int x = 5;
std::shared_ptr<int> p(&x); // 错误:x 会被释放两次
应改为:
cpp复制编辑auto p = std::make_shared<int>(5);
cpp复制编辑classMyClass : public std::enable_shared_from_this<MyClass> {
voidf() {
auto self = shared_from_this(); // 正确获取当前 shared_ptr
}
};
使用场景 | 推荐智能指针 |
---|---|
独占资源、无共享 | unique_ptr |
多个对象共享所有权 | shared_ptr |
弱引用、观察者模式 | weak_ptr |
原始指针无所有权需求 | 原始指针(只读) |
cpp复制编辑unique_ptr > shared_ptr > raw pointer > weak_ptr(观察者/缓存)
创建角色类 Player 和装备类 Weapon,使用智能指针管理内存与生命周期。
cpp复制编辑classWeapon {
public:
Weapon(std::string name) : name(name) {}
~Weapon() { std::cout << "Weapon destroyed\n"; }
private:
std::string name;
};
classPlayer {
public:
std::shared_ptr<Weapon> weapon;
};
cpp复制编辑intmain() {
auto sword = std::make_shared<Weapon>("Excalibur");
Player p1, p2;
p1.weapon = sword;
p2.weapon = sword;
std::cout << "Use count: " << sword.use_count() << "\n";
}
智能指针是现代 C++ 编程中不可或缺的工具。掌握其用法不仅可以避免内存泄漏,更是实现高质量代码的基础。开发者应根据场景选择最合适的指针类型,避免过度使用 shared_ptr,在设计阶段就思考生命周期与所有权关系。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。