11年前关闭了。
pimpl: shared_ptr or unique_ptrsmart pointers (boost) explained有人能解释一下shared_ptr和unique_ptr之间的区别吗?
tzdcorbm1#
这两个类都是智能指针,这意味着当它们所指向的对象不再被引用时,它们会自动(在大多数情况下)释放该对象。两者之间的区别在于每种类型可以引用资源的不同指针的数量。使用unique_ptr时,最多只能有一个unique_ptr指向任何一个资源。当该unique_ptr被销毁时,资源将自动回收。由于任何资源只能有一个unique_ptr,因此任何复制unique_ptr的尝试都将导致编译时错误。例如,以下代码是非法的:
unique_ptr
unique_ptr<T> myPtr(new T); // Okay unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
但是,unique_ptr可以使用新的移动语义进行 * move *:
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被销毁时,该资源将被释放。例如,下面的代码是完全合法的:
auto_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使用reference counting来跟踪有多少指针引用了一个资源,因此需要注意不要引入任何引用循环。简而言之:1.当您希望有一个指向对象的单指针时,使用unique_ptr,该对象将在该单指针被销毁时被回收。1.当需要指向同一资源的多个指针时,请使用shared_ptr。
avwztpqn2#
如果您在某个地方只有一个动态对象,而 * 一个 * 使用者拥有唯一的对象,那么unique_ptr是一种轻量级智能指针(因此是“唯一的”)责任--可能是需要维护某个动态分配的对象的 Package 器类。unique_ptr的开销非常小。它不可复制,但可移动。它的 type 是template <typename D, typename Deleter> class unique_ptr;,因此它依赖于两个模板参数。unique_ptr也是auto_ptr希望在旧的C++中实现的,但由于该语言的限制而无法实现。另一方面,shared_ptr是一种非常不同的动物。明显的区别是,你可以让许多消费者分担一个动态对象的责任(因此“共享”),只有当所有共享指针都消失时,这个对象才会被销毁。此外,你可以观察 * 弱指针 *,如果它们所跟踪的共享指针消失,它们会被智能地通知。在内部,shared_ptr有很多功能:有一个引用计数,它被原子地更新以允许在并发代码中使用。此外,还有大量的分配正在进行,一个用于内部簿记“引用控制块”,另一个(经常)用于实际的成员对象。但还有一个很大的区别:共享指针的类型是alwaystemplate <typename T> class shared_ptr;,尽管你可以用自定义的删除器 * 和自定义的分配器 * 来初始化它,删除器和分配器是用类型擦除和虚函数分派来跟踪的,这增加了类的内部权重,但是有一个巨大的优势,即不同种类的T类型的共享指针都是兼容的。无论删除和分配的细节。因此,他们真正表达了“共担责任的T“的概念,而不负担消费者的细节!shared_ptr和unique_ptr都设计为通过值传递(对唯一指针有明显的可移动性要求),但都不应该让您担心开销,因为它们的功能确实令人震惊,但如果可以选择,请首选unique_ptr,只有在确实需要分担责任时才使用shared_ptr。
template <typename D, typename Deleter> class unique_ptr;
template <typename T> class shared_ptr;
T
xxhby3vn3#
唯一指针
是独占拥有对象的智能指针。
共享指针
是共享所有权的智能指针。它既是copyable又是movable。多个智能指针示例可以拥有同一资源。拥有该资源的最后一个智能指针一旦超出范围,该资源将被释放。
copyable
movable
0mkxixxg4#
当在unique_ptr中 Package 指针时,您不能有unique_ptr的多个副本。shared_ptr包含一个引用计数器,该计数器计算存储指针的副本数。每次复制shared_ptr时,该计数器递增。每次析构shared_ptr时,该计数器递减。当该计数器达到0时,则销毁存储对象。
4条答案
按热度按时间tzdcorbm1#
这两个类都是智能指针,这意味着当它们所指向的对象不再被引用时,它们会自动(在大多数情况下)释放该对象。两者之间的区别在于每种类型可以引用资源的不同指针的数量。
使用
unique_ptr
时,最多只能有一个unique_ptr
指向任何一个资源。当该unique_ptr
被销毁时,资源将自动回收。由于任何资源只能有一个unique_ptr
,因此任何复制unique_ptr
的尝试都将导致编译时错误。例如,以下代码是非法的:但是,
unique_ptr
可以使用新的移动语义进行 * move *:类似地,您可以执行以下操作:
这个习惯用法的意思是"我将一个托管资源返回给你。如果你没有显式地捕获返回值,那么这个资源将被清除。如果你捕获了,那么你现在就拥有了这个资源的独占所有权。"这样,你可以认为
unique_ptr
是auto_ptr
的一个更安全、更好的替代品。另一方面,
shared_ptr
允许多个指针指向一个给定的资源。当最后一个指向资源的shared_ptr
被销毁时,该资源将被释放。例如,下面的代码是完全合法的:在内部,
shared_ptr
使用reference counting来跟踪有多少指针引用了一个资源,因此需要注意不要引入任何引用循环。简而言之:
1.当您希望有一个指向对象的单指针时,使用
unique_ptr
,该对象将在该单指针被销毁时被回收。1.当需要指向同一资源的多个指针时,请使用
shared_ptr
。avwztpqn2#
如果您在某个地方只有一个动态对象,而 * 一个 * 使用者拥有唯一的对象,那么
unique_ptr
是一种轻量级智能指针(因此是“唯一的”)责任--可能是需要维护某个动态分配的对象的 Package 器类。unique_ptr
的开销非常小。它不可复制,但可移动。它的 type 是template <typename D, typename Deleter> class unique_ptr;
,因此它依赖于两个模板参数。unique_ptr
也是auto_ptr
希望在旧的C++中实现的,但由于该语言的限制而无法实现。另一方面,
shared_ptr
是一种非常不同的动物。明显的区别是,你可以让许多消费者分担一个动态对象的责任(因此“共享”),只有当所有共享指针都消失时,这个对象才会被销毁。此外,你可以观察 * 弱指针 *,如果它们所跟踪的共享指针消失,它们会被智能地通知。在内部,
shared_ptr
有很多功能:有一个引用计数,它被原子地更新以允许在并发代码中使用。此外,还有大量的分配正在进行,一个用于内部簿记“引用控制块”,另一个(经常)用于实际的成员对象。但还有一个很大的区别:共享指针的类型是always
template <typename T> class shared_ptr;
,尽管你可以用自定义的删除器 * 和自定义的分配器 * 来初始化它,删除器和分配器是用类型擦除和虚函数分派来跟踪的,这增加了类的内部权重,但是有一个巨大的优势,即不同种类的T
类型的共享指针都是兼容的。无论删除和分配的细节。因此,他们真正表达了“共担责任的T
“的概念,而不负担消费者的细节!shared_ptr
和unique_ptr
都设计为通过值传递(对唯一指针有明显的可移动性要求),但都不应该让您担心开销,因为它们的功能确实令人震惊,但如果可以选择,请首选unique_ptr
,只有在确实需要分担责任时才使用shared_ptr
。xxhby3vn3#
唯一指针
是独占拥有对象的智能指针。
共享指针
是共享所有权的智能指针。它既是
copyable
又是movable
。多个智能指针示例可以拥有同一资源。拥有该资源的最后一个智能指针一旦超出范围,该资源将被释放。0mkxixxg4#
当在
unique_ptr
中 Package 指针时,您不能有unique_ptr
的多个副本。shared_ptr
包含一个引用计数器,该计数器计算存储指针的副本数。每次复制shared_ptr
时,该计数器递增。每次析构shared_ptr
时,该计数器递减。当该计数器达到0时,则销毁存储对象。