tem*_*def 470

这两个类都是智能指针,这意味着它们会自动(在大多数情况下)释放它们在不再引用该对象时指向的对象.两者之间的区别在于每种类型的指针有多少可以引用资源.

使用时unique_ptr,最多只能unique_ptr指向一个资源.当它unique_ptr被销毁时,资源会自动回收.因为unique_ptr任何资源只能有一个,所以任何复制a的尝试unique_ptr都会导致编译时错误.例如,此代码是非法的:

unique_ptr<T> myPtr(new T);       // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
Run Code Online (Sandbox Code Playgroud)

然而,unique_ptr移动使用新的移动语义:

unique_ptr<T> myPtr(new T);                  // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr
Run Code Online (Sandbox Code Playgroud)

同样,你可以这样做:

unique_ptr<T> MyFunction() {
    unique_ptr<T> myPtr(/* ... */);

    /* ... */

    return myPtr;
}
Run Code Online (Sandbox Code Playgroud)

这个成语意味着"我正在向您返回托管资源.如果您没有明确捕获返回值,那么资源将被清除.如果您这样做,那么您现在拥有该资源的独占所有权." 通过这种方式,您可以将其unique_ptr视为更安全,更好的替代品auto_ptr.

shared_ptr另一方面,允许多个指针指向给定资源.当shared_ptr资源的最后一个被销毁时,资源将被释放.例如,此代码完全合法:

shared_ptr<T> myPtr(new T);       // Okay
shared_ptr<T> myOtherPtr = myPtr; // Sure!  Now have two pointers to the resource.
Run Code Online (Sandbox Code Playgroud)

在内部,shared_ptr使用引用计数来跟踪有多少指针引用资源,因此您需要注意不要引入任何引用周期.

简而言之:

  1. 使用unique_ptr时您需要一个指针时单指针被销毁,将被回收的对象.
  2. shared_ptr当您想要多个指向同一资源的指针时使用.

希望这可以帮助!

  • 对于删除者来说,`unique_ptr`可能是一个小小的错误.`shared_ptr`将始终做"正确的事情",只要它是用`make_shared`创建的.但是如果你创建一个`unique_ptr <Derived>`,然后将它转换为`unique_ptr <Base>`,如果Derived是虚拟的而Base不是,那么指针将被错误的类型删除,并且可能存在未定义的行为.这可以通过`unique_ptr <T,DeleterType>`中的相应删除类型来修复,但默认情况下使用风险较高的版本,因为它更有效. (15认同)
  • @AaronMcDaid默认情况下`unique_ptr`的行为就像一个你不能忘记`删除`的原始指针:如果你忘记让dtor虚拟,那就在你身上. (3认同)
  • 我更喜欢使用 `make_unique` 而不是 `new`。它更清洁、更安全、更高效。 (2认同)
  • @templatetypedef 你能举一个例子来说明如何将 `MyFunction()` 的返回值捕获到调用者作用域中的另一个指针中吗? (2认同)

Ker*_* SB 74

unique_ptr是一个轻量级的智能指针,如果你只有一个动态对象,一个消费者有唯一的(因此"独特")责任 - 可能是一个需要维护一些动态分配对象的包装类.unique_ptr开销很小.它不可复制,但可移动.它的类型template <typename D, typename Deleter> class unique_ptr;,所以它取决于两个模板参数.

unique_ptr也是auto_ptr想要在旧的C++中,但由于该语言的限制而无法实现.

shared_ptr另一方面是一种非常不同的动物.显而易见的区别在于,您可以让许多消费者共同负责动态对象(因此"共享"),并且只有在所有共享指针消失后才会销毁该对象.此外,您可以观察弱指针,如果他们关注的共享指针消失,将会智能地通知它们.

在内部,shared_ptr还有更多内容:有一个引用计数,它以原子方式更新以允许在并发代码中使用.此外,还有大量的分配,一个用于内部簿记"参考控制块",另一个用于实际的成员对象.

但是还有另一个很大的区别:共享指针类型总是如此 template <typename T> class shared_ptr;,尽管您可以使用自定义删除器自定义分配器对其进行初始化.使用类型擦除和虚函数调度来跟踪删除和分配器,这增加了类的内部权重,但是具有巨大的优点,即不同类型的共享指针T都是兼容的,无论删除和分配细节如何.因此,他们真正表达了"共同责任T" 的概念,而不会给消费者带来细节!

二者shared_ptrunique_ptr设计成由值传递(与用于唯一的指针明显的可移动性要求).也不应该让你担心开销,因为他们的力量确实令人震惊,但如果你有选择,更喜欢unique_ptr,只有shared_ptr在你真正需要共同责任时才使用.

  • @ splinter123:通过移动它! (10认同)
  • "旨在通过价值传递"? (4认同)
  • 由于我对shared_ptr的引用计数器实际上在哪里感到困惑(毕竟,多个shared_ptrs和单个共享资源意味着单个共享引用计数器太对了?所以计数器不能包含在shared_ptr中).这是我见过的第一个回答我问题的shared_ptr解释; 分配了单独的参考计数器.据推测,它在计数0-> 1时分配一次,在计数1-> 0时释放一次,就像受控资源一样. (3认同)
  • @Farzan:是的,正是如此。要么使用临时函数(根据定义您无权访问该函数)调用该函数,要么需要传递诸如“std::move(x)”之类的内容作为参数,这意味着“x”随后被移出。 (2认同)

Alo*_*ave 18

unique_ptr
是一个智能指针,它只拥有一个对象.

shared_ptr
是共享所有权的智能指针.这是copyablemovable.多个智能指针实例可以拥有相同的资源.一旦拥有资源的最后一个智能指针超出范围,资源就会被释放.


neo*_*phi 9

在指针中包装指针时,unique_ptr不能有多个副本unique_ptr.的shared_ptr保持参考计数器,它计数所存储的指针的副本的数目.每次shared_ptr复制a时,此计数器都会递增.每次a shared_ptr被破坏时,该计数器递减.当此计数器达到0时,存储的对象将被销毁.