C++智能指针:unique_ptr、shared_ptr、weak_ptr

本文介绍了C++中的智能指针,包括unique_ptr、shared_ptr和weak_ptr的用途和操作。unique_ptr独占对象所有权,不支持多重共享;shared_ptr允许多个指针共享对象,通过引用计数管理内存,可能导致循环引用;weak_ptr是弱引用,用于解决shared_ptr的循环引用问题。文章讨论了各种智能指针的常见操作和使用注意事项。
摘要由CSDN通过智能技术生成

为什么需要智能指针

程序使用动态内存出于以下三种原因之一:

  1. 程序不知道自己需要使用多少对象
  2. 程序不知道所需对象的准确类型
  3. 程序需要在多个对象间共享数据

而在C++中动态内存的管理是通过一对运算符来完成的,即newdelete,但是动态内存的使用很容易产生以下问题:

  • 忘记delete内存,导致内存泄露问题,而且这种问题很难排查,往往出现在程序运行阶段而不是编译阶段。

  • 使用已释放的对象。

    通过释放内存后,将指针置为空,有时可以检测出这种错误

  • 同一块内存被释放两次。当两个指针指向相同的动态分配对象时,如果其中一个指针进行了delete操作,对象的内存就被归还给自由空间了,如果我们随后又delete第二个指针,自由空间就可能被破坏。
    在这里插入图片描述
    所以为了使开发人员能够更容易更安全的使用动态内存,就需要智能指针,智能指针的使用类似于指针,最主要的区别是它负责自动释放所指向的对象,目前有3种智能指针,分别是:

  • shared_ptr:允许多个指针指向同一个对象

  • unique_ptr:独占所指向的对象

  • weak_ptr:弱引用,指向shared_ptr所管理的对象

STL一共提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr

auto_ptr功能类似于unique_ptr,但是其在C++11中已经废弃,被unique_ptr替代,原因是auto_ptr不够安全,且支持拷贝和赋值,如p2= p1,p2会接管p1原来的内存管理权,p1会变为空指针,如果p2原来不为空,则它会释放原来的资源,基于这个原因,应该避免将auto_ptr放到容器中,因为算法对容器操作时,很难避免STL内部对容器实现了赋值传递操作,这样会使容器中很多元素被置为NULL。

在C++17中auto_ptr已被废除。

unique_ptr

一个unique_ptr拥有它所指向的对象。某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它指向的对象也被销毁。

由于unique_ptr独占的特点,所以unique_ptr不支持普通的拷贝或者赋值操作(拷贝或赋值一个将要被销毁的unique_ptr例外,比如函数返回一个unique_ptr),定义一个unique_ptr时,需要将其绑定到一个new返回的指针上,且也必须使用直接初始化方式

例如:unique_ptrp(new int(10))

unique_ptr常用操作

  • u.release():u放弃对指针的控制权,返回内置指针(即new出来的指针),并将u置为空

    class A {
         
    public:
    	~A() {
         
    		cout << "~A()" << endl;
    	}
    };
    int main()
    {
         
    	unique_ptr<A>p1(new A);
    	//错误:release函数只是将p1置为空,并不会释放其指向的内存。而运行后并没有任何输出,说明没有调用A的析构函数,也说明release函数不会释放其指向的内存。
    	p1.release();
    	return 0;
    }
    

    注意:该操作通常用来初始化另一个智能指针,如果我们不用另一个智能指针保存其返回的指针,我们的程序就要负责资源的释放

  • u.reset():释放u指向的对象

  • u.reset(q):令u指向q,q必须是内置指针;

通过release或reset将指针的所有权从一个(非const)unique_ptr转移给另一个unique_ptr;

int main()
{
   
	unique_ptr<int>p1(new int(10));
	unique_ptr<int>p2(p1.release()); //release将p1置空,并指针的控制权交给p2
	p1.get() ? (cout << "p1的值为:" << *p1.get() << endl) : (cout << "p1为空指针" << endl);
	p2.get() ? (cout << "p2的值为:" << *p2.get() << endl) : (cout << "p2为空指针" << endl);
	unique_ptr<int>p3(new int(20));
	p2.reset(p3.release());//将所有权从p3转交给p2,并释放原先p2指向的对象
	p2.get() ? (cout << "p2的值为:" << *p2.get() << endl) : (cout << "p2为空指针" << endl);
	p3.get() ? (cout << "p3的值为:" << *p3.get(</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倒地不起的土豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值