14.5.4 unique_ptr
因此,make_vec()是一种很有用的函数,在出现异常的情况下,它遵循了好的资源管理的基本原则。在我们想从异常中恢复时,它提供了基本保证——与所有实现良好的函数一样。它甚至能提供强保证,除非在“向vector填充数据”这部分代码中对非局部数据进行了糟糕操作。尽管如此,try…catch这部分代码仍然是丑陋的。解决方法很明显:我们必须以某种方式使用RAII;也就是说,我们需要提供一个对象以容纳vector<int>对象,以使得当异常发生时它能够销毁vector对象。为此,在<memory>中标准库提供了unique_ptr:
unique_ptr是一种能存储指针的对象。我们用new返回的对象立即初始化unique_ptr对象。与指针一样,我们可以对unique_ptr使用->和*运算符(例如p->at(2)或(*p).at(2)),因此我们可以将unique_ptr看作一种指针。但是,unique_ptr拥有所指向的对象:当销毁unique_ptr时,它会delete所指向的对象。这意味着如果在向vector<int>填充数据时抛出了异常,或者我们过早从返回make_vec,vector<int>会被恰当地销毁。p.release()会从p中提取出所保存的(指向vector<int>的)指针,从而我们可以返回它,它还使得p保存的指针变为nullptr,从而销毁p(return所做的事情)不会销毁任何对象。
unique_ptr的使用极大地简化了make_vec()。基本上,它令make_vec()变得与朴素的不安全版本一样简单。重要的是,使用unique_ptr令我们可以反复做我们建议的事情——用怀疑的目光看待显式的try块;就像make_vec()中那样,大多数try块可以被“资源获取即初始化”技术的某种变体所替代。 ...
