C++11智能指针(shared_ptr/weak_ptr/unique_ptr/auto_ptr)详细讲解

智能指针是什么?

C++11中有shared_ptr与weak_ptr、unique_ptr等智能指针(smart pointer),定义在<memory>中。可以对动态资源进行管理,保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用

shared_ptr

介绍

shared_ptr允许多个该智能指针“同时管理/拥有”同一堆分配对象的内存,这通过引用计数实现,会记录有多少个shared_ptr共同指向一个对象,一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。
通俗的来讲,比如放学之后,教室的灯没有具体的管理者,我们会让最后一个走的人关灯,这就是shared_ptr的一个通俗解释。

一些使用场景

  • 对象之间“共享数据”,对象创建与销毁“分离”。
  • 放入容器中的动态对象,C++STL的容器在其生命周期结束的时候会调用该类的析构函数,也就是对容器中的每一个对象都调用对应的析构函数,此时shared_ptr的计数变量会不断减一,直到减为零的时候会删除该智能指针指向的对象。
int main() {
    shared_ptr<int> sptr1(new int(123));
    shared_ptr<int> sptr2 = sptr1;
    
    cout << "count: " << sptr2.use_count() << '\n'; //2
    
    sptr1.reset();    //引用计数减1(重置该智能指针的指向)
    cout << "count: " << sptr2.use_count() << '\n'; //1
    
    return 0;
}

可能会出现的问题

当shared_ptr出现循环引用的时候,会出现内存泄漏,两个shared_ptr循环引用的时候会使这两个shared_ptr的计数变量都不会清零,所以不会调用指向对象的析构函数,导致内存泄漏,解决方法:weak_ptr。

weak_ptr

介绍

weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少

weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。

shared_ptr会共享对象的所有权,但是有一些场景如果有一个像shared_ptr但是又不参与资源所有权共享的指针是很方便的。换句话说,是一个类似shared_ptr但不影响对象引用计数的指针。不参与资源所有权就意味着不会对资源的生命周期产生影响,有利于对象之间解除关系。

一些使用场景

For example A和B相互加了好友,假设我们用一个指针来指向自己的好友,如果是shared_ptr,那么A和B的生命周期是相互影响的,而实际上我们并不希望这种强绑定,假设B注销了账户,A根本不用知道,只有当A想发消息给B的时候系统才会发出提示:你还不是该用户的朋友。这时,我们就需要使用weak_ptr(当你想使用对象,但是并不想管理对象,并且在需要使用对象时可以判断对象是否还存在)。

int main() {
    shared_ptr<int> sptr1(new int(123));
    shared_ptr<int> sptr2 = sptr1;
    weak_ptr<int> wptr = sptr1; // 指向shared_ptr<int> sptr1所指向的对象

    cout << "count: " << wptr.use_count() << '\n'; // 2

    sptr1.reset();
    cout << "count: " << wptr.use_count() << '\n'; // 1

    sptr2.reset();
    cout << "count: " << wptr.use_count() << '\n'; // 0

    return 0;
}

unique_ptr

介绍

unique_ptr持有对对象的独有权,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义只有移动语义(move)来实现)。
unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。
离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。

int main() {
    unique_ptr<int> uptr1(new int(123));
    //unique_ptr<int> uptr2 = uptr1;        // 不能通过编译,同时只能有一个unique_ptr指向同一对象
    unique_ptr<int> uptr3 = move(uptr1);    // 使用移动语义,现在uptr3是数据的唯一的unique_ptr
    uptr3.reset();            				// 释放内存
    uptr1.reset();            				// 不会导致运行时错误
    
    uptr4.reset(new int(1234)); 			//"绑定"动态对象
    uptr4 = nullptr;						//显式销毁所指对象,同时智能指针变为空指针。与up4.reset()等价
    
    unique_ptr<int> uptr5(new int(12345));
    int *p = uptr5.release(); 				//只是释放控制权,不会释放内存,返回之前管理内存的地址
    delete p; 								//释放堆区资源
    
    return 0;
}

auto_ptr

C++17中被删除。不做过多解释~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值