C++ 智能指针

STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr,模板auto_ptr是C++98提供的解决方案,C+11已将将其摒弃。
使用注意点:

  • 包含头文件 #include <memory>
  • 所有的智能指针类都有一个explicit构造函数,以指针作为参数,因此不能自动将指针转换为智能指针对象,必须显式调用
  • 智能指针只能应用于堆内存
string vacation("I wandered lonely as a cloud.");
shared_ptr<string> pvac(&vacation);   // No,pvac过期时,程序将把delete运算符用于非堆内存,这是错误的

为什么摒弃auto_ptr?

  • 当把一个auto_ptr赋给另外一个auto_ptr时,它的所有权也转移了,如果再次访问原指针,会造成野指针问题
  • auto_ptr不能指向一组对象,就是说它不能和操作符new[]一起使用
  • auto_ptr不能和标准容器(vector,list,map…)一起使用

unique_ptr为何优于auto_ptr?

  • 当程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;否则编译器将禁止这么做。
	unique_ptr<string> pu1(new string ("hello world"));
	unique_ptr<string> pu2;
	pu2 = pu1;   // #1 not allowed
	unique_ptr<string> pu3;
	pu3 = unique_ptr<string>(new string ("You"));   // #2 allowed
  • std::move(),让你能够将一个unique_ptr赋给另一个,使用move后,原来的指针仍转让所有权变成空指针,可以对其重新赋值
	unique_ptr<string> ps1, ps2;
	ps1 = demo("hello");
	ps2 = move(ps1);
	ps1 = demo("alexia");
	cout << *ps2 << *ps1 << endl;
  • unique_ptr提供了创建数组对象的特殊方法,当指针离开作用域时,调用delete[]代替delete。当创建unique_ptr时,这一组对象被视作模板参数的部分。这样,程序员就不需要再提供一个指定的析构方法
	unique_ptr<int[ ]> uptr( new int[5] );

share_ptr循环引用

在这里插入图片描述
如图所示,即使对象ptr_a和ptr_b被销毁,也就是①③两条引用会被断开,但是②④两条引用依然存在,每一个的引用计数都不为0,结果就导致其指向的内部对象无法析构,造成内存泄漏。

解决这种状况的办法就是将两个类中的一个成员变量改为weak_ptr对象,因为weak_ptr不会增加引用计数,使得引用不形成环,最后就可以正常的释放内部的对象。
在这里插入图片描述
对象ptr_a和ptr_b被销毁,也就是①③两条引用会被断开,此时CA对象的引用计数会减为0,对象被销毁,其内部的m_ptr_b成员变量也会被析构,导致CB对象的引用计数会减为0,对象被销毁,进而解决了引用成环的问题。

weak_ptr不支持普通指针包含的*,->操作。它并不包含资源所以也不允许程序员操作资源,如果需要使用它,需要使用expired函数来检测是否过期,因为它本身不会增加引用计数,所以它指向的对象可能在它用的时候已经被释放了,然后使用lock函数来获取其对应的shared_ptr对象,然后进行后续操作。

weak_ptr<T> w;	 	//创建空 weak_ptr,可以指向类型为 T 的对象
weak_ptr<T> w(sp);	//与 shared_ptr 指向相同的对象,shared_ptr 引用计数不变。T必须能转换为 sp 指向的类型
w=p;				//p 可以是 shared_ptr 或 weak_ptr,赋值后 w 与 p 共享对象
w.reset();			//将 w 置空
w.use_count();		//返回与 w 共享对象的 shared_ptr 的数量
w.expired();		//若 w.use_count() 为 0,返回 true,否则返回 false
w.lock();			//如果 expired() 为 true,返回一个空 shared_ptr,否则返回非空 shared_ptr
void main( )
{
	 shared_ptr<Test> sptr( new Test );
	 weak_ptr<Test> wptr( sptr );
	 if (!wptr.expired())		//判断 weak_ptr 观察的对象是否失效
	 {
		 shared_ptr<Test> sptr2 = wptr.lock( );
	 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值