C++基础(九)-shared_ptr,weak_ptr与unique_ptr

1.定义

  • shared_ptr 和 unique_ptr 是 C++11 引入的智能指针,用于自动管理动态内存,防止内存泄漏。它们的主要区别在于所有权语义。

2.使用

2.1 unique_ptr(独占指针)
2.1.1 简单使用
#include <memory>
// 创建独占指针
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
// 错误:不能复制
// std::unique_ptr<int> ptr2 = ptr1;
// 可以移动所有权
std::unique_ptr<int> ptr2 = std::move(ptr1);  // ptr1 现在为 nullptr
// 自定义删除器
auto deleter = [](int* p) { delete p; std::cout << "deleted\n"; };
std::unique_ptr<int, decltype(deleter)> ptr3(new int(10), deleter);
2.1.2 特点
  • 独占资源所有权
  • 离开作用域时自动释放内存
  • 支持数组版本:unique_ptr<T[]>
  • 可以自定义删除器
2.2 shared_ptr(共享指针)
#include <memory>
// 创建共享指针(推荐使用 make_shared)
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
// 可以复制,引用计数增加
std::shared_ptr<int> ptr2 = ptr1;  // 引用计数: 2
std::shared_ptr<int> ptr3 = ptr2;  // 引用计数: 3
// 一个指针离开作用域
{
    std::shared_ptr<int> ptr4 = ptr3;  // 引用计数: 4
}  // ptr4 销毁,引用计数: 3
// 自定义删除器
std::shared_ptr<int> ptr4(new int(100), [](int* p) {
    delete p;
    std::cout << "custom delete\n";
});
2.2 shared_ptr与weak_ptr(共享指针)
  • 不会增加引用计数
#include <memory>
std::shared_ptr<int> sp = std::make_shared<int>(42);
// 创建 weak_ptr
std::weak_ptr<int> wp1 = sp;  // 从 shared_ptr 构造
std::weak_ptr<int> wp2;
// 赋值操作
wp2 = wp1;                    // ✅ 允许:weak_ptr 之间赋值
wp2 = sp;                     // ✅ 允许:从 shared_ptr 赋值
// wp2 = std::make_shared<int>(10);  // ✅ 也可以
std::cout << "sp.use_count() = " << sp.use_count() << std::endl;  // 输出: 1
// weak_ptr 赋值不会增加引用计数!
  • weak_ptr 的关键方法

lock() - 安全获取 shared_ptr

#include <iostream>
#include <memory>
int main() {
    std::shared_ptr<int> sp = std::make_shared<int>(42);
    std::weak_ptr<int> wp = sp;
        // 方法1:检查后再打印
    std::shared_ptr<int> locked = wp.lock();
    if (locked) {
        std::cout << "wp指向的值: " << *locked << std::endl;
        std::cout << "引用计数: " << locked.use_count() << std::endl;  // 输出: 2
    } else {
        std::cout << "对象已销毁" << std::endl;
    }
        // 方法2:使用临时变量(推荐)
    if (auto sp2 = wp.lock()) {
        std::cout << "值: " << *sp2 << std::endl;
    }
        return 0;
}
2.2.1 注意
  • weak_ptr 是一个观察者。本身不存储值,只存储一个指向控制块的指针
  • 必须先 lock() 获取 shared_ptr 才能访问值
  • lock() 会增加引用计数(临时增加)-
  • 如果对象已销毁,lock() 返回空的 shared_ptr
2.3 选择指南
  • 默认使用 unique_ptr - 除非需要共享所有权
  • 优先使用 make_unique/make_shared - 异常安全且高效
  • 使用 shared_ptr 时注意循环引用 - 必要时使用 weak_ptr
  • 避免裸指针与智能指针混用
  • 不要使用 shared_ptr 管理数组 - 用 unique_ptr<T[]> 或 vector

总结

  • unique_ptr: "这个资源只属于我,我负责释放"
  • shared_ptr: "这个资源我们可以共享,最后一个使用者负责释放"
  • 根据所有权的需求选择合适的智能指针,能有效避免内存泄漏,使代码更安全清晰。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容