有人可以解释一下shared_ptr和unique_ptr之间的区别吗?
有人可以解释一下shared_ptr和unique_ptr之间的区别吗?
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
然而,unique_ptr
可以使用新的移动语义进行移动:
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr
unique_ptr<T> MyFunction() {
unique_ptr<T> myPtr(/* ... */);
/* ... */
return myPtr;
}
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.
在内部,shared_ptr
使用引用计数来跟踪有多少指针引用资源,因此您需要小心不要引入任何引用循环。
简而言之:
unique_ptr
。shared_ptr
。unique_ptr
在处理删除器方面可能会有一些小 bug。只要使用 make_shared
创建,shared_ptr
就总是会做“正确的事情”。但是如果你创建了一个 unique_ptr<Derived>
,然后将其转换为 unique_ptr<Base>
,并且 Derived 是虚拟的而 Base 不是,则指针将通过错误类型进行删除,并且可能会导致未定义的行为。可以使用适当的删除器类型在 unique_ptr<T, DeleterType>
中进行修复,但默认情况下使用较高风险的版本,因为它更加高效。 - Aaron McDaidunique_ptr
的行为类似于一个你不会忘记delete
的原始指针:如果你忘记使析构函数为虚函数,那就是你的责任。 - curiousguymake_unique
而不是new
。它更加简洁、安全和高效。 - SubMachineMyFunction()
的返回值捕获到调用者范围内的另一个指针中吗? - Vassilisunique_ptr
是轻量级的智能指针,如果你有一个动态对象,只有一个消费者(因此“unique”)负责, 例如需要维护一些动态分配的对象的包装类,那么它就是首选。 unique_ptr
几乎没有开销。它不可复制,但可移动。其类型为template <typename D, typename Deleter> class unique_ptr;
,所以它依赖于两个模板参数。
unique_ptr
也是旧版C++中auto_ptr
想要成为的东西,但由于该语言的限制而无法实现。
另一方面,shared_ptr
则是一个非常不同的概念。明显的区别是,您可以让多个消费者共享动态对象的责任(因此“shared”),并且仅在所有共享指针都消失时才会销毁对象。此外,您可以拥有观察弱指针,这些指针将智能地被通知,如果它们跟随的共享指针已经消失。
内部,shared_ptr
具有更多的功能:有一个引用计数,它会被原子方式更新以允许在并发代码中使用。此外,还有大量的分配操作,一个用于内部记账“引用控制块”,另一个(通常)用于实际成员对象。
但是还有另一个重要的区别:共享指针的类型始终为template <typename T> class shared_ptr;
,尽管您可以使用自定义删除器和自定义分配器进行初始化。删除器和分配器使用类型擦除和虚函数调度进行跟踪,这增加了类的内部负担,但具有巨大的优势,即不同类型的T
的共享指针都是兼容的,无论删除和分配的细节如何。因此,它们真正表达了“对T
的共享责任”的概念,而不会给消费者带来负担!
无论shared_ptr
还是unique_ptr
都被设计为按值传递(对于唯一指针,显然需要可移动性)。由于它们的强大功能,两者都不应让您担心开销,但如果您有选择,则应首选unique_ptr
,只有在确实需要共享责任时才使用shared_ptr
。
std::move(x)
这样的参数,这意味着x
被移动。 - Kerrek SBunique_ptr
是一种独占对象的智能指针。
shared_ptr
是一种用于共享所有权的智能指针,它支持拷贝和移动。多个智能指针实例可以共同拥有同一个资源。只要最后一个拥有该资源的智能指针超出范围,该资源就会被释放。
当用unique_ptr
包装一个指针时,你不能拥有多个unique_ptr
的副本。而shared_ptr
则持有一个引用计数器来统计所存储指针的副本数量。每次复制shared_ptr
时,该计数器会增加一次;每次销毁shared_ptr
时,该计数器会减少一次。当这个计数器减少到0时,存储的对象就会被销毁。