从另一个 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共享智能指针的初始化与使用

在 C++ 中使用 shared_ptr 的指针的意外行为

我啥时候想从原始指针构造一个共享指针

智能指针std::shared_ptr初始化时可能泄露的地方

Boost python,将原始指针与托管指针进行比较?