共享指针是怎么回事?
我的程序由于添加了指向向量的指针而失败。经过大量阅读和删除后,我将其更改为将共享指针添加到集合中(使用插入),一开始很好,但现在也失败了。我尝试了两种解决方案;两者都不起作用。其中一个也失败了,而另一种(make共享类型)则无法编译。
阅读更多内容后,我发现了这个 论坛 其中指出,我不应该指向具有两个不同共享指针的对象,而应该创建它的副本。那么共享指针的最大区别是什么......?
My program fails due to addition of a pointer to a vector. After much reading and deleting I have changed it to an addition of a shared pointer into a set (using insert) which was fine at first but now fails as well. I tried two solutions; neither worked. One failed as well and the other, the make shared kind, did not compile.
Reading a bit more I came upon this forum which states, that I shouldn't point to something with two different shared pointers but rather create a copy of it. So what is the big difference of the shared pointer...?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一切都与所有权有关。如果实体(函数或对象)负责确保删除指针,则该实体(函数或对象)被称为“拥有”指针。每当您使用
new
时,某人、某处都必须取得返回指针的所有权。如果不是这种情况,则存在内存泄漏。各种智能指针的目的都是对某种形式的所有权进行建模。智能指针的析构函数是可以触发指针删除的。
std::auto_ptr
(只要你不复制它)模型单一所有权。也就是说,任何拥有 auto_ptr 实例的实体都是会导致该指针被破坏的实体。感谢黑客技术,复制auto_ptr
实际上将所有权从复制的对象转移到要复制到的对象(注意:永远不要这样做)。所以,如果你有这个:
它肯定会被销毁(只要持有它的实体被正确清理)。当
p1
脱离堆栈时,指针将被销毁。如果p1
是类的成员,那么当该类实例被销毁时,指针将被销毁。指针的生命周期是有范围的。 Boost 实际上有一个不可复制的等效项,称为 boost::scoped_ptr。使用任何类型的智能指针时都必须遵守几条规则。这是最重要的。
规则#1:如果您从裸指针构造一个智能指针实例,那么您所说的是,“当前没有对象拥有此指针的所有权。我现在< em>将所有权交给您,即智能指针。”这就是从裸指针构造智能指针对象的含义。
此代码违反了规则 #1:
auto_ptr::get()
函数返回指针,因此这是合法的 C++ 代码(可以编译)。但是,p1
和p2
现在都认为它们拥有该指针。因为auto_ptr
仅模型单一所有权,这是不允许的。当p2
被销毁时,它将删除该指针。然后,当p1
被销毁时,它将尝试删除相同指针。哎呀。
现在我们已经非常清楚规则#1了,让我们看看
shared_ptr
。这个智能指针模型共享所有权。多个实体可以同时声明指针的所有权。仅当全部都使用完该指针后,该指针才会被删除。因此,如果 3 个对象都包含同一对象的shared_ptr
,则在删除所有包含shared_ptr
的三个对象之前,该对象不会被删除。重要的是要理解
shared_ptr
是一个智能指针。因此,它受规则#1 的约束。这可能没有道理。毕竟,它应该允许共享所有权。这一定意味着这是允许的,对吧?
没有。这仍然是错误的。
auto_ptr
和shared_ptr
之间的区别在于,您可以使用shared_ptr
来执行此操作:这是
p2
的复制构造代码>p1。从裸指针创建shared_ptr
与从现有shared_ptr
创建共享指针之间存在根本区别。后者实际上是两者之间共享所有权的东西。前者只会造成坏事。因此,如果您有一个裸指针并将其放入
shared_ptr
中,则只能对该指针执行一次。如果您想共享所有权,则必须复制它。有一个半后门:
enable_shared_from_this
。如果您从此类型派生一个类,那么您的类将具有一个shared_from_this
私有成员,该类的成员函数可使用该成员来转移所有权。所以:除此之外,您还必须通过显式复制对象来转移所有权。
It's all about ownership. An entity (a function or object) is said to "own" a pointer if it is that entity's job to ensure that the pointer is deleted. Any time you use
new
, someone, somewhere must take ownership of the pointer returned. If this is not the case, you have a memory leak.The purpose of all kinds of smart pointers is to model some form of ownership. The destructor of the smart pointer is what can trigger the deletion of the pointer.
std::auto_ptr
(as long as you don't copy it) models single-ownership. That is, whatever entity has theauto_ptr
instance is the entity that will cause that pointer's destruction. Thanks to hackery, copying anauto_ptr
actually transfers ownership from the copied object to the object being copied to (note: never do this).So, if you have this:
This is guaranteed to be destroyed (so long as the entity holding it is properly cleaned up). When
p1
falls off the stack, the pointer will be destroyed. Ifp1
were a member of a class, then the pointer will be destroyed when that class instance is destroyed. The lifetime of the pointer is scoped. Boost actually has a non-copyable equivalent calledboost::scoped_ptr
.There are several rules that you must abide by when using any kind of smart pointers. This is the most important.
Rule #1: If you construct a smart pointer instance from a naked pointer, what you are saying is, "No object currently has ownership of this pointer. I am now giving ownership to you, the smart pointer." That is what it means to construct a smart pointer object from a naked pointer.
This code is a violation of Rule #1:
The
auto_ptr::get()
function returns the pointer, so this is legal C++ code (it compiles). However, bothp1
andp2
now think that they own the pointer. Becauseauto_ptr
only models single-ownership, that is not allowed. Whenp2
is destroyed, it will delete the pointer. Then, whenp1
is destroyed, it will try to delete the same pointer.Oops.
Now that we're all very clear on Rule #1, let's look at
shared_ptr
. This smart pointer models shared ownership. Multiple entities can claim ownership of the pointer at the same time. The pointer will only be deleted when all of them are finished using it. So if 3 objects all contain ashared_ptr
to the same object, that object will not be deleted until all three that contain theshared_ptr
are deleted.It is important to understand that
shared_ptr
is a smart pointer. And therefore, it is subject to Rule #1.That may not make sense. After all, it's supposed to allow shared ownership. That must mean that this is allowable, right?
Nope. This is still wrong. The difference between
auto_ptr
andshared_ptr
is that you can do this withshared_ptr
:That's copy construction of
p2
fromp1
. There is a fundamental difference between creating ashared_ptr
from a naked pointer and creating one from an already existingshared_ptr
. The latter is what actually shares ownership between the two. The former will just cause badness.Therefore, if you ever have a naked pointer and put it in a
shared_ptr
, you can only do this for that pointer one time. If you want to share ownership, you must copy it around.There is one semi-backdoor:
enable_shared_from_this
. If you derive a class from this type, then your class will have ashared_from_this
private member that member functions of the class can use to transfer ownership around. So:Other than that, you'll have to transfer ownership by explicitly copying the object around.
shared_ptr
,顾名思义,如果从不同的地方引用了shared_ptr指向的对象,则应该使用shared_ptr。例如 - 类 A1 和 A2 应该使用相同的 S 类型对象。因此两者都应该持有指向 S 的指针。但是谁独占它(谁应该删除它)。就说A1吧。因此,A1 在其析构函数中将删除 S。但是,如果 A1 在 A2 之前被销毁,会发生什么情况 - A2 将具有指向 S 的悬空指针(指向已删除对象的指针)。使用共享指针而不是指向 S 的原始指针 (S*) 可以解决此问题。
shared_ptr
, as its name states, should be used if an object, pointed by shared_ptr, is referenced from different places.For example - class A1 and A2 should use same object of type S. So both should hold pointer to S. But who exclusively owns its (who should delete it). Let's say A1. So, A1 in its destructor will delete S. But what happen if A1 is destroyed before A2 - A2 will have dangling pointer (pointer to deleted object) to S. Using shared_ptr instead of raw pointer to S (S*) solves this problem.
共享指针取得所指向对象的所有权。
其语义是,当复制shared_ptr时,每个人依次共享一个句柄,以获取其共享的所有权知识。当最后一个副本被销毁时,它就销毁了该对象。这使您不必在正确的时间手动管理对
delete
的调用,并且(希望)使内存泄漏更少。为了做到这一点,正常的风格是在创建shared_ptr时为其提供一个
new
堆对象,并避免此后直接使用原始指针。您在STL集中使用shared_ptr是正确的。这是确保集合被销毁时对象被清理的正确方法。
The shared pointer takes ownership of the object pointed to.
The semantics of this is that when the shared_ptr is copied, each in turns shares a handle to their shared knowledge of the ownership. When the last copy is destroyed, it destroys the object. This saves you from having to manually manage the call to
delete
at the right time, and (hopefully) make memory leaks rarer.To make this work, the normal style is to give a
new
heap object to a shared_ptr when it is created, and avoid thereafter directly working with the raw pointer.You are correct in using shared_ptr within the STL set. This is the right way to ensure that the object is cleaned up when the set is destroyed.