从另一个 shared_ptr 的原始指针生成 shared_ptr
Posted
技术标签:
【中文标题】从另一个 shared_ptr 的原始指针生成 shared_ptr【英文标题】:Making shared_ptr from the raw pointer of another shared_ptr 【发布时间】:2020-07-17 18:08:52 【问题描述】:说,我有一个shared_ptr<A> ptrFirst
,它已初始化并指向内存中的某个对象。现在,我像这样定义一个新的shared_ptr
:
shared_ptr<A> ptrSecond = make_shared<A>(ptrFirst.get());
我知道我可以使用简单的分配来防止出现任何问题。但是我想知道如果我这样定义ptrSecond,我会为同一个对象有两个不同的控制块吗?这还很糟糕吗?
【问题讨论】:
在析构函数中设置断点。 TLDR:这很糟糕。 这里还有另一个案例,实际的minimal reproducible example 会有很大帮助,因为它会发现其他人指出的问题。反过来,这将导致要么不需要问这个问题,要么问一个更好的问题。 【参考方案1】:除非您有一个将A*
作为唯一参数的构造函数,否则您的行不会编译事件。
如果您确实有构造函数A::A(A*)
,那么make_shared
将创建一个新对象 - 这很好。
如果您改用std::shared_ptr
构造函数:
std::shared_ptr<A> ptrSecond = std::shared_ptr<A>(ptrFirst.get());
那就有问题了。这将导致双重释放,即UB。
【讨论】:
【参考方案2】:但我想知道如果我这样定义ptrSecond,我会为同一个对象有两个不同的控制块吗?
没有。这段代码:
shared_ptr<A> ptrSecond = make_shared<A>(ptrFirst.get());
逻辑上等于:
shared_ptr<A> ptrSecond( new A( ptrFirst.get() ) );
所以基本上它将创建A
的新实例并使用指向另一个A
的指针对其进行初始化,当然只有在您定义了正确的ctor 时它才会编译。
这还很糟糕吗?
如果你的意思是这样的:
shared_ptr<A> ptrSecond( ptrFirst.get() );
是的,这很糟糕,因为它会由于双重释放而导致 UB。
【讨论】:
更糟糕的是,如果您在第一个指针被销毁后尝试使用第二个指针,您也会得到 UB。以上是关于从另一个 shared_ptr 的原始指针生成 shared_ptr的主要内容,如果未能解决你的问题,请参考以下文章
[C++11]shared_ptr使用的注意事项(内存被重复析构,内存泄漏问题)
[C++11]shared_ptr共享智能指针的初始化与使用