好的,所以我最后一次以编写 C 为生,std::auto_ptr是所有可用的标准库,并且boost::shared_ptr风靡一时。我从来没有真正研究过提供的其他智能指针类型提升。我知道 C11 现在提供了一些 boost 提出的类型,但不是全部。
std::auto_ptr
boost::shared_ptr
那么有人有一个简单的算法来确定何时使用哪个智能指针吗?最好包括关于哑指针(原始指针,如T*)和其余 boost 智能指针的建议。(这样]()的东西会很棒。
T*
按值传递,除非当
const
几乎从不建议通过指针传递。可选参数最好表示为std::optional(boost::optional对于较旧的标准库),并且通过引用可以很好地完成别名。
std::optional
boost::optional
C++11 的移动语义使得按值传递和返回即使对于复杂对象也更具吸引力。
通过const引用传递参数,除非当
NULL
0
nullptr
(这里,“按值传递”称为“按副本传递”,因为按值传递总是在 C++03 中创建副本)
还有更多,但是这几个初学者的规则会让你走得很远。
共享所有权: 采用的标准shared_ptr与Boost 对应weak_ptr的标准几乎相同。当您需要共享资源并且不知道哪一个将是最后一个还活着时,请使用它们。用于在不影响其生命周期的情况下观察共享资源,而不是破坏循环。通常不应该发生循环- 两个资源不能相互拥有。weak_ptr``shared_ptr
shared_ptr
weak_ptr
weak_ptr``shared_ptr
请注意,Boost 还提供了shared_array,这可能是shared_ptr<std::vector<T> const>.
shared_array
shared_ptr<std::vector<T> const>
接下来,Boost 提供intrusive_ptr了一个轻量级的解决方案,如果您的资源已经提供了引用计数管理并且您希望将其应用于 RAII 原则。这个标准没有被采纳。
intrusive_ptr
唯一所有权:* Boost 也有一个scoped_ptr,它是不可复制的,你不能为其指定一个删除器。std::unique_ptr是类固醇, 当您需要智能指针时boost::scoped_ptr应该是您的默认选择。它允许您在其模板参数中指定删除器,并且是 可移动 的,与. 只要您不使用需要可复制类型的操作(显然),它也可以在 STL 容器中完全使用。 * __boost::scoped_ptr
scoped_ptr
std::unique_ptr
boost::scoped_ptr
再次注意,Boost 有一个数组版本:scoped_array,标准通过要求std::unique_ptr<T[]>部分特化来统一它,它将delete[]指针而不是deleteing 它(使用default_deleter)。std::unique_ptr<T[]>还提供operator[]代替operator*and operator->。
scoped_array
std::unique_ptr<T[]>
delete[]
delete
default_delete
operator[]
operator*
operator->
请注意,std::auto_ptr它仍在标准中,但已 弃用 。 搂D.10 [depr.auto.ptr]
搂D.10 [depr.auto.ptr]
类模板auto_ptr已弃用。[ 注: 类模板unique_ptr(20.7.1)提供了更好的解决方案。 ”第二注 ]
auto_ptr
unique_ptr
无所有权: 使用哑指针(原始指针)或对资源的 非拥有引用的引用 ,并且当您知道该 资源将比 引用对象/范围更长时。当您需要可空性或可重置性时,首选引用并使用原始指针。
如果您想要对资源的非拥有引用,但您不知道该资源是否会比引用它的对象寿命长,请将资源打包shared_ptr并使用 a weak_ptr- 您可以测试父级shared_ptr是否存在于lock,这将如果资源仍然存在,则返回shared_ptr非空值。如果要测试资源是否已死,请使用expired. 两者可能听起来很相似,但在并发执行方面却有很大不同,因为expired只保证了它对单个语句的返回值。一个看似无辜的测试
lock
expired
if(!wptr.expired()) something_assuming_the_resource_is_still_alive();
是一个潜在的竞争条件。