16.2
16.2 智能指针模板类
智能指针是行为类似于指针的类对象, 但这种对象还有其他功能。
介绍三个可帮助管理动态内存分配的智能指针模板。
栈解退解决方案:智能指针类
auto_ptr类(仅C++98可用)
unique_ptr类 // C++11
shared_ptr类 // C++11
weak_ptr类 // 不讨论
使用智能指针
三个智能指针模板都定义了类似指针的对象, 可以将new获得的地址赋值给这种对象。
当智能指针过期时, 其析构函数将使用delete释放内存。
因此, 无需记住稍后释放这些内存。
头文件:
auto_ptr pd(new double);
unique_ptr pdu(new double);
shared_ptr pds(new string);
使用智能指针将不再需要delete, 离开代码块时, 指针将过期。
每个智能指针类都有一个explicit构造函数:必须使用显式转换普通指针
智能指针很多方面类似于普通指针, 还可以将智能指针对象赋值给另一个同类型的智能指针对象。但可能会引起一个问题。下一节讨论。
不能用于非堆内存。
有关智能指针的注意事项
auto_ptr智能指针相互赋值时, 所有权将从一个智能指针交给另一个智能指针, 没有所有权的指针对象将会被删除。
shared_ptr将使用引用计数, 允许多个智能指针指向同一块空间, 最后一个智能指针过期时, 调用delete
unique_ptr和auto_ptr相同,但是不会在运行时造成程序崩溃, 而是提示出现错误。
unique_ptr为何优于auto_ptr
有时, 将一个智能指针赋值给另一个智能指针并不会留下危险的悬挂指针————将unique_ptr作为函数返回值。
如果源unique_ptr是一个临时右值, 编译器允许这样做, 如果源unique_ptr将存在一段时间, 编译器禁止这样做。
而auto_ptr允许两种赋值。
仅当以非智能的方式使用智能指针时——如解除引用:
保准库函数:
std::move()
ps2 = std::move(ps1);
如何区分unique_ptr安全和不安全的用法:使用了C++11新增的移动构造函数和右值引用。第十八章讨论。
另外一个优点:
它有一个可以用于数组的变体:
模板auto_ptr使用delete而不是delete[], 因此只能和new一起使用。
但unique_ptr有使用delete[]和delete的版本。
std::unique_ptr< double [] > pda(new double [5]);
shared_ptr也不能使用new[]。
选择智能指针
STL容器可以包含智能指针:允许shared_ptr的赋值和复制操作, 但是不支持其他两个智能指针。
需要多个指针指向同一个内存空间——shared_ptr
不需要多个指针同时指向一个内存空间——unique_ptr
unique_ptr可以按引用传递
unique_ptr可以被赋值给shared_ptr(和unique_ptr相互赋值相同)
shared_ptr包含一个显式的构造函数,可以接管unique_ptr所有的对象。