头文件 #include <memory>
std::auto_ptr
#include <iostream>#include <memory>using namespace std;class T {public:T() {cout << "constructor called" << endl;}~T() {cout << "destructor called" << endl;}};int main() {cout << "--------begin-----------" << endl;{cout << 1 << endl;auto_ptr<T> t1(new T);cout << 2 << endl;auto_ptr<T> t2 = t1; // 此处会让t1的指向变成nullcout << 3 << endl;if (!t1.get()) {cout << "t1 is null" << endl;}cout << 4 << endl;}cout << "--------end-----------" << endl;return 0;}
auto_ptr在copy、assignment时会使得源指针的指向变成null,导致程序出现诡异行为,故而已被弃用
编译时的提示
运行结果
std::unique_ptr
用来替代autu_ptr。
默认情况下,unique_ptr与裸指针有着相同的大小,对于大多数操作执行几乎相同的命令,性能接近裸指针。
unique_ptr不可复制,是个只移型别。
unique_ptr可以自定义删除器。
unique_ptr可以方便高效地转化为shared_ptr。
class Base {};unique_ptr<Base> f() {return unique_ptr<Base>(new Base);}int main(){auto pbd = [](Base* b) {cout << "delete b" << endl;delete b;};unique_ptr<Base, decltype(pbd)> upb(new Base, pbd);shared_ptr<Base> spb = f();return 0;}
std::shared_ptr
shared_ptr采用引用计数来进行垃圾收集。
shared_ptr有另一个指针指向一块堆上的内存,保存了包括引用计数、自定义删除器等数据,故shared_ptr的大小是裸指针的2倍。
shared_ptr指定删除器不需要给定模板参数shared_ptr<Base> spb(new Base, pbd);
将this指针传递给shared_ptr有坑,解决办法可以看《Effective Modern c++》
unique_ptr
#include <iostream>#include <memory>using namespace std;class T {private:static int id;int tid;public:T() {tid = id++;cout << "id = " << tid << " constructor called" << endl;}~T() {cout << "id = " << tid << " destructor called" << endl;}};int T::id = 1;int main() {cout << "--------begin-----------" << endl;{cout << 1 << endl;shared_ptr<T> t1(new T);cout << 2 << endl;shared_ptr<T> t2(new T);cout << 3 << endl;shared_ptr<T> t3 = t1;cout << 4 << endl;if (!t1.get()) {cout << "t1 is null" << endl;}cout << 5 << endl;t2 = t1; // t2改变指向,会销毁id=2的对象cout << 6 << endl;}cout << "--------end-----------" << endl;return 0;}
std::weak_ptr
可以指向一块由shared_ptr指向的内存,但是不参与引用计数。
可以用weak_ptr来创建shared_ptr。
shared_ptr<Base> spb(new Base);weak_ptr<Base> wpb(spb);shared_ptr<Base> spb2 = wpb.lock();shared_ptr<Base> spb3(wpb);
std::make_shared
优先选用make_shared
make系函数不能自定义析构器。
make_shared会进行一些优化将控制块和对象内存分配到一起。
使用new指针初始化shared_ptr会有2次内存分配(1次对象,1次控制块),当引用计数为0时,对象内存释放,当弱计数(用于weak_ptr)为0时,控制块内存释放。
使用make函数初始化shared_ptr会将2者分配到一个内存块,只有一次内存申请,但是引用计数为0并不会释放内存块,必须等到弱计数为0时才会释放。
