C++ 智能指针总结

本文介绍了C++11引入的三种智能指针:std::unique_ptr(独占资源所有权)、std::shared_ptr(共享资源所有权,使用引用计数管理内存)和std::weak_ptr(共享资源的观察者,避免循环引用问题)。文章列举并解析了std::shared_ptr的两个常见错误用法,包括双删问题和循环引用导致的内存泄漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++11 引入了 3智能指针类型:

  • std::unique_ptr<T> :独占资源所有权的指针;
  • std::shared_ptr<T> :共享资源所有权的指针,它的原理是使用引用计数实现对同一块内存的多个引用,在最后一个引用被释放时,指向的内存才释放;
  • std::weak_ptr<T> :共享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。
1. std::unique_ptr
{
    std::unique_ptr<int> uptr = std::make_unique<int>(200);
    std::unique_ptr<int> uptr1 = uptr;  // 编译错误,std::unique_ptr<T> 是 move-only 的

    std::unique_ptr<int> uptr2 = std::move(uptr); // 转为右值后
    assert(uptr == nullptr);
}
2. std::shared_ptr
{
    std::shared_ptr<int> sptr = std::make_shared<int>(200);
    assert(sptr.use_count() == 1);  // 此时引用计数为 1
    {   
        std::shared_ptr<int> sptr1 = sptr;
        assert(sptr.get() == sptr1.get());
        assert(sptr.use_count() == 2);   // sptr 和 sptr1 共享资源,引用计数为 2
    }   
    assert(sptr.use_count() == 1);   // sptr1 已经释放
}
// use_count 为 0 时自动释放内存
错误用法1:退出{ }p1、p2都会对p0析构,导致p0被删除两次,报错;
{
	int *p0 = new int(1);
    shared_ptr<int> p1(p0);
    shared_ptr<int> p2(p0);
}
错误用法2:循环引用;
struct Father{
    shared_ptr<Son> son_;
};

struct Son{
    shared_ptr<Father> father_;
};

int main(){
    auto father = make_shared<Father>();
    auto son = make_shared<Son>();
    father->son_ = son;
    son->father_ = father;
    return 0;
}

main 函数退出之前,Father_objSon_obj的引用计数都是 2,退出main后,引用计数为1,导致对象没法被销毁,从而引起内存泄漏。

3. std::weak_ptr

std::weak_ptr弱引用指针std::shared_ptr强引用指针),弱引用指针不会增加引用计数。
使用std::weak_ptr修正错误用法2:

struct Father{
    shared_ptr<Son> son_;
};

struct Son{
    weak_ptr<Father> father_;
};

int main(){
    auto father = make_shared<Father>(); // father ptr points to a Father obj
    auto son = make_shared<Son>();

    father->son_ = son;
    son->father_ = father;
    return 0;
}
  1. 退出main之前,Son_obj引用数为2Father_obj引用为1;
  2. 退出main后,son 指针被销毁 ⇒ Son_obj引用数为1;
          father 指针被销毁 ⇒ father_obj引用数为0;
  3. father_obj引用数为0Father_obj被析构 ⇒ Father_obj.son被销毁⇒ Son_obj引用数为0Son_obj被析构;
  4. 最终father_objSon_obj被正常析构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值