c++++中的智能指针unique_ptr和shared_ptr通过raii机制自动管理内存生命周期,避免内存泄漏和野指针问题。1. unique_ptr强调独占所有权,资源只能被一个指针持有,不可复制只能移动,适用于单一所有者明确控制资源生命周期的场景,如工厂函数返回值、类成员变量、局部变量管理动态内存;2. shared_ptr允许多个指针共享资源,通过引用计数决定释放时机,适合生命周期依赖多个持有者的场景,如缓存机制、观察者模式、图结构节点、共享配置数据等;3. shared_ptr存在循环引用导致内存泄漏的风险,需引入weak_ptr打破循环,weak_ptr不增加引用计数,仅用于临时访问shared_ptr管理的对象;4. 实际项目中应优先考虑unique_ptr,因其轻量高效,只有在确实需要共享所有权时才使用shared_ptr,并警惕循环引用问题,合理使用weak_ptr规避风险。

现代C++中的智能指针,尤其是
unique_ptr
shared_ptr
unique_ptr
unique_ptr
shared_ptr

在C++11及以后的版本里,智能指针几乎成了动态内存管理的标准答案。过去我们手动
new
delete
unique_ptr
unique_ptr
unique_ptr
unique_ptr
立即学习“C++免费学习笔记(深入)”;

而
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
unique_ptr
unique_ptr
unique_ptr

想想那些需要明确生命周期的资源:
std::unique_ptr<MyClass> createMyObject() {
return std::make_unique<MyClass>();
}
// 调用者获得所有权
auto obj = createMyObject();这里,
createMyObject
MyClass
obj
obj
MyClass
class ResourceManager {
public:
ResourceManager() : data_(std::make_unique<int>(100)) {}
// ...
private:
std::unique_ptr<int> data_; // data_的生命周期与ResourceManager实例绑定
};void processLargeData() {
std::unique_ptr<double[]> buffer = std::make_unique<double[]>(1024 * 1024);
// 使用buffer进行计算
// 函数结束时,buffer自动释放
}unique_ptr
unique_ptr
shared_ptr
shared_ptr
shared_ptr
典型的使用场景包括:
缓存机制:多个客户端可能需要访问同一个缓存项。只要有客户端还在使用这个缓存项,它就应该存在。
观察者模式:一个主题对象可能被多个观察者共享,只要有观察者还“观察”着它,它就不应该被销毁。
图结构中的节点:图中的一个节点可能被多个其他节点引用,其生命周期取决于所有引用它的节点。
共享配置或数据:应用程序中多个模块需要访问同一份配置数据,并且这份数据的生命周期与所有模块相关。
class Config { /* ... */ };
std::shared_ptr<Config> globalConfig = std::make_shared<Config>();
void moduleA(std::shared_ptr<Config> cfg) { /* 使用cfg */ }
void moduleB(std::shared_ptr<Config> cfg) { /* 使用cfg */ }
// moduleA和moduleB可以同时持有globalConfig的引用
// 只有当所有shared_ptr都不再引用它时,globalConfig才会被销毁然而,
shared_ptr
shared_ptr
例如:
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A destroyed" << std::endl; }
};
class B {
public:
std::shared_ptr<A> a_ptr;
~B() { std::cout << "B destroyed" << std::endl; }
};
void test_circular_dependency() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a;
// 此时a和b的引用计数都为2。
// 当a和b离开作用域时,它们的引用计数会减到1,但永远不会到0,导致内存泄漏。
}为了解决这个问题,C++引入了
std::weak_ptr
weak_ptr
shared_ptr
weak_ptr
lock()
shared_ptr
lock()
shared_ptr
class B;
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A destroyed" << std::endl; }
};
class B {
public:
std::weak_ptr<A> a_ptr; // 使用weak_ptr打破循环
~B() { std::cout << "B destroyed" << std::endl; }
};
void test_fixed_circular_dependency() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a; // 此时a的引用计数为1,b的引用计数为1
// 当a和b离开作用域时,它们的引用计数都会减到0,对象会被正确销毁。
}shared_ptr
unique_ptr
shared_ptr
在实际的C++项目开发中,选择
unique_ptr
shared_ptr
优先考虑unique_ptr
unique_ptr
当且仅当需要共享所有权时才使用shared_ptr
shared_ptr
shared_ptr
警惕循环引用,必要时引入weak_ptr
shared_ptr
shared_ptr
weak_ptr
shared_ptr
weak_ptr::lock()
shared_ptr
lock()
shared_ptr
从设计层面思考所有权语义: 在编写代码之前,先花点时间思考你正在处理的资源的“所有权”模型。这个资源是谁创建的?谁负责销毁它?它会同时被多少个地方使用?这些使用者之间是平等的共享关系,还是有明确的主次关系?一旦你对这些问题有了清晰的答案,选择合适的智能指针就水到渠成了。比如,如果一个对象是某个聚合类的一部分,并且其生命周期完全由聚合类控制,那么
unique_ptr
shared_ptr
总的来说,现代C++的智能指针是解决内存管理难题的强大工具。理解
unique_ptr
shared_ptr
weak_ptr
以上就是现代C++智能指针有哪些类型 shared_ptr unique_ptr使用场景对比的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号