一、为何要使用智能指针
1. 考虑下边的简单代码:
int main()
{
int *ptr = new int(0);
return 0;
}
一不小心就忘了释放掉已不再使用的内存,从而导致资源泄漏(resoure leak,在这里也就是内存泄漏)。
2. 考虑另一简单代码:
int main()
{
int *ptr = new int(0);
delete ptr;
return 0;
}
上边程序虽然最后释放了申请的内存,但ptr会变成空悬指针(dangling pointer,也就是野指针)。空悬指针不同于空指针(nullptr),它会指向“垃圾”内存,给程序带去诸多隐患(如我们无法用if语句来判断野指针)。
ptr = nullptr;
3.考虑到的两个问题,上边程序还存在另一问题:如果内存申请不成功,new会抛出异常,而我们却什么都没有做!所以对这程序我们还得继续改进(也可用try...catch...):
#include <iostream>
using namespace std;
int main()
{
int *ptr = new(nothrow) int(0);
if(!ptr)
{
cout << "new fails."
return 0;
}
// 假定hasException函数原型是 bool hasException()
if (hasException())
{
delete ptr;
ptr = nullptr;
throw exception();
}
delete ptr;
ptr = nullptr;
return 0;
}
我们使用智能指针的原因至少有以下三点:
1)智能指针能够帮助我们处理资源泄露问题;
2)它也能够帮我们处理空悬指针的问题;
3)它还能够帮我们处理比较隐晦的由异常造成的资源泄露。
二、shared_ptr
共享式拥有,多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用(reference)被销毁”时候释放。
三、unique_ptr
独占式拥有,保证同一时间内只有一个智能指针可以指向该对象。
四、weak_ptr
不控制所指对象生存周期的智能指针,它指向一个shared_ptr所管理的对象。一个weak_ptr绑定到shared_ptr并不会改变引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象。
创建一个weak_ptr, 要用一个shared_ptr来初始化。
shared_ptr<int> p = make_shared<int>(42);
weak_ptr<int> wp(p);
我们不能使用weak_ptr直接访问对象,必须调用lock检查所指向的对象是否存在,lock会返回一个指向共享对象的shared_ptr。
if(shared_ptr<int> np = wp.lock()){ // 不空才满足if条件
//在if中np与p共享对象
}
五、auto_ptr
C++98中,它具有unique_ptr的部分特性,但不是全部。特别我们不能在容器中保存auto_ptr, 也不能函数返回auto_ptr。
虽然它仍是标准库的一部分,但编写程序时尽量用unique_ptr。
参考:《C++Primer》
https://www.cnblogs.com/xiehongfeng100/p/4645555.html#autoid-3-0-0