智能指针
智能指针实际上是一个重载了"*"、"->"、"[]"等特殊符号来达到类似指针使用方法效果的一个类。其作用是避免传统指针使用时,忘记释放,造成内存泄漏。用这种新式指针,满足RAII原则(资源申请初始化——"构造时获得,析构时释放")的同时,使使用形式简单化。
c++ 11中的3个智能指针类型:
-
std::unique_ptr
当我们独占资源的所有权的时候,可以使用
std::unique_ptr
对资源进行管理——离开unique_ptr
对象的作用域时,会自动释放资源。通俗来说,一个对象一次只能由
std::unique_ptr<T>
的 一个实例来管理,当这个对象被std::unique_ptr<T>
的其他实例管理时,原实例会被置为空。正因如此,不允许调用
std::unique_ptr<T>
的拷贝构造函数,
使用形式如下:
{
std::unique_ptr<int> uptr = std::make_unique<int>(200);
// 离开 uptr 的作用域的时候自动释放内存
}
-
std::shared_ptr
std::shared_ptr
可以由许多共享std::shared_ptr<T>
的实例的接管者。std::shared_ptr<T>
内置了一个引用计数器,监视当前有多少个std::shared_ptr<T>
实例。当最后一个实例被销毁,智能指针就会释放持有的资源。std::shared_ptr<T>
可以拷贝,也可以用std::move强行移动它指向的资源。但被移动后,此 std::shared_ptr
变量就会变成nullptr
。一个 shared_ptr 对象的内存开销要比裸指针的 unique_ptr 对象略大:
std::cout << sizeof(int*) << std::endl; // 输出 8 std::cout << sizeof(std::unique_ptr<int>) << std::endl; // 输出 8 std::cout << sizeof(std::shared_ptr<int>) << std::endl; // 输出 16
shared_ptr 需要维护的信息有两部分:
1.指向共享资源的指针。
2.引用计数等共享资源的控制信息——实际是维护一个指向控制信息的指针。所以,shared_ptr 对象需要保存两个指针。
当我们创建一个 shared_ptr 时,其实现一般如下:
std::shared_ptr<T> sptr1(new T);
复制一个 shared_ptr :
std::shared_ptr<T> sptr2 = sptr1;
-
std::weak_ptr
如何检测
shared_ptr<T>
管理的资源是否有效呢,此时可以使用std::weak_ptr
, 一个std::weak_ptr
对象可以看做是std::shared_ptr
对象管理着的资源的观察者,它不影响共享资源的生命周期:-
如果需要使用
weak_ptr
正在观察的资源,可以将weak_ptr
提升为shared_ptr
。 -
当
shared_ptr
管理的资源被释放时,weak_ptr
会自动变成nullptr
。
-
当 shared_ptr 析构并释放共享资源的时候,只要 weak_ptr 对象还存在,控制块就会保留,weak_ptr 可以通过控制块观察到对象是否存活。
参考自 1. https://zhuanlan.zhihu.com/p/150555165 2. 《clean C++》