【问题标题】:Delete raw pointer after creating a shared_ptr from it从中创建 shared_ptr 后删除原始指针
【发布时间】:2015-06-09 04:41:57
【问题描述】:

如果我执行以下操作,

int* p = new int(10);
std::shared_ptr<int>(p);
delete p;

这里发生了什么?删除原始指针后shared_ptr 是否无效?这种情况下有什么办法可以保证内存访问安全吗?

【问题讨论】:

  • 请问您为什么需要这样做?我的意思是为什么不首先使用shared_ptr
  • 我有一个以 shared_ptr 作为参数的函数。我只是想找出如果 API 的客户端像上面那样做愚蠢的事情,我的函数会出现异常的情况,并看看我的函数中是否可以做任何事情来阻止这种情况的发生。有什么想法吗?
  • 不,如果您的客户决定朝自己的脚开枪,您无能为力。
  • 有什么可以做的吗?我倾向于怀疑它。有志者事竟成。

标签: c++ c++11 segmentation-fault shared-ptr raw-pointer


【解决方案1】:

您问题中的代码包含两个相互冲突的 p 定义。我假设您打算发布类似

的内容
int* p = new int(10);
std::shared_ptr<int> p1(p);
delete p;

shared_ptr 超出范围且其引用计数降至零时,它将尝试delete p;,从而导致双重删除和未定义行为。

您已将动态分配的int 的所有权传递给shared_ptr,所以让它完成它的工作,不要自己去删除int


如果您希望 API 的客户端执行与上述代码类似的操作,一种可能性是将 API 函数的参数类型从 shared_ptr 更改为构造函数参数的参数包。比如

template<typename T, typename... Args>
void api_func(Args&&... args)
{
    auto p = std::make_shared<T>(std::forward<Args>(args)...);
    // Use the shared_ptr p as before
}

然后,客户端代码不会传递shared_ptr&lt;int&gt;,而是将上述函数调用为api_func&lt;int&gt;(10);

【讨论】:

  • std::shared_ptr&lt;int&gt;(p); 创建一个临时值。它不是p 的声明。在调用delete p; 时,内存已被shared_ptr 析构函数释放。
  • @tsuki 不,这里的括号是多余的,所以它是一个名为 pshared_ptr&lt;int&gt; 的声明(在这种情况下,它是 p 的重新声明,因此是一个错误)。跨度>
  • 嗯,这很有趣。抱歉,我试图在不运行代码的情况下变得聪明。
  • @tsuki 想一想,也许 OP 意味着使用大括号而不是括号。 std::shared_ptr&lt;int&gt;{p};会完全按照你在第一条评论中所说的去做。但最终结果是相同的,未定义的行为。
  • @rozina 这是我最初的假设,但由于某些奇怪的原因,您可以将变量名括起来,但仍然可以获得变量声明。那是一些奇怪的 C++ 怪癖……
猜你喜欢
  • 1970-01-01
  • 2019-09-29
  • 1970-01-01
  • 2016-02-23
  • 2021-11-15
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多