智能指针
原生指针是一款很强大的工具,但是依据进数十年的经验,可以确定的一点是:稍有不慎,这 个工具就会反噬它的使用者。
C++11标准中规定了四个智能指针:
std::auto_ptr,std::unique_ptr,std::shared_ptr,std::weak_ptr.他们都是用来辅助管理动态分配对象的声明周期。
std::unique_ptr
当要使用一个智能指针的时候,首先要想到的应该是std::unique_ptr。默认情况下,std::unique_ptr和原生指针同等大小,对于大多数操作,他们执行的底层指令也一样。
std::unique_ptr具现了独占语义,一个非空的std::unique_ptr永远拥有它指向的对象。
很容易将一个std::unique_ptr转化为std::shared_ptr.
std::unique_ptr<Widget> getWidget();
std::shared_ptr<Widget> pWidget = getWidget();
std::shared_ptr
std::shared_ptr通过引用计数来管理对象的生命周期。std::shared_ptr的构造函数自动递增这个计数,析构函数自动递减这个计数。如果std::shared_ptr在执行减一后发现引用计数变成了0,说明没有其他的std::shared_ptr在指向这个资源了,所以std::shared_ptr直接析构了它指向的空间。
std::shared_ptr是std::unique_ptr的两倍大,除了控制块,还有需要原子引用计数操作引起的开销
避免从原生指针类型变量创建std::shared_ptr,若无法避免,请使用new
auto pw = new Widget;
std::shared_ptr<Widget> spw1(pw);
std::shared_ptr<Widget> spw2(pw); // 到此为止,为pw创建了两个智能指针,且其计数都分别为1,当进行释放时,第一次析构没有问题,第二次析构时pw已经不存在了,这就产生了一个未定义行为
std::shared_ptr spw1(new Widget); // 直接使用new
std::shared_ptr spw2(spw1); // 这样就没有问题了
std::weak_ptr
std::weak_ptr不能被单独使用,它是std::shared_ptr作为参数的产物。std::weak_ptr通常有一个std::shared_ptr来创建,他们指向相同地址,std::shared_ptr来初始化他们,但是std::weak_ptr不会影响到它所指对象的引用计数。
auto spw = std::make_shared<Widget>();
std::weak_ptr<Widget> wpw(spw);
spw = nullptr;
if (wpw.expired())
{
/* code */
}