目前裸指针存在的问题:
-
无法从一个裸指针中看出指针指向的是单个对象还是对象数组;
-
无法了解裸指针是否唯一拥有这块内存,这影响是否需要用该指针进行析构操作;
-
即使需要进行析构,那么内存释放时使用free还是delete还是delete[]呢?
-
无法保证指针指向的内存一定会被释放,也无法保证只会被释放一次;
-
无法判断这个指针指向的内存是否已经释放,是否是个野指针;
条款十八:使用std::unique_ptr管理具备专属所有权的资源
针对上面几个问题,std::unique_ptr都有了可靠的解决方案:
-
std::unique_ptr具有std::unique_ptr<T>和std::unique_ptr<T[]>两种形式来区分单个对象和数组;
-
std::unique_ptr作为一个只移型别,保证了资源的专属所有权;
-
它默认使用delete运算符析构,也可以自定义析构器;
-
作为一个只移型别的对象,保证了会且仅会释放一次;
-
只会在函数结束之后释放,释放之后就取不到了。而且移动之后可以通过判空判断原指针是否有效;
通常情况下,std::unique_ptr跟裸指针几乎一样大,但是有状态的析构器和采用函数指针实现的析构器会增加unique对象的尺寸大小。
std::unique_ptr可以很容易的转换成std::shared_ptr, 这就带来了一种改进后的工厂模式。
class Investment {...}; class Stock: public Investment {...}; template<typename T> auto makeInvestment(T& param) { std::unique_ptr<Investment> pInv(nullptr); if(...) { pInv.reset(new Stock(std:forward<T>(param))); } ... return pInv; }; std::shard_ptr<Investment> sp = makeInvestment(param); // 转换为std::shared_ptr型别
条款十九:使用std::shared_ptr管理具备共享所有权的资源
std::shared_ptr通过引用计数来确定自己是不是最后一个涉及到该资源的指针,在引用计数变成0之后,std::shared_ptr就会析构,释放资源。
也正是因为增加了引用计数,std::shared_ptr存在一些性能上的影响: