【问题标题】:How std::shared_ptr is deallocated?std::shared_ptr 如何被释放?
【发布时间】:2020-11-30 21:42:33
【问题描述】:

以下代码中的内存释放何时发生?

#include <memory>

int main()
{
    auto p = std::make_shared<int>(5);
    
    std::weak_ptr<int> wp = p;
    
    p = nullptr;
    
    return wp.lock() == nullptr ? 0 : 1;
}

如下来自this post std::make_shared 执行一个堆分配。这是否意味着在至少有一个std::weak_ptr 还活着之前,内存不能被释放?

【问题讨论】:

  • 在所有 shared_ptr 被破坏或重置后,weak_ptr 将保持内存中的 控制块“活动”,直到所有弱指针都被破坏。使用make_shared 将在一次分配中为对象分配控制块和空间,因此weak_ptr 将保留控制块的内存和被破坏的对象的内存,直到所有weak_ptr 都被破坏。
  • @Eljay 我预计会发生某种奇迹,但你让我失望了...... :)
  • 唉,C++ 中没有奇迹。不过,有很多令人难以置信的聪明东西!我听说过尝试将 垃圾收集 与 C++ 结合,但我自己还没有尝试过那种内存管理奇迹。

标签: c++ c++17


【解决方案1】:

(必须编辑答案,因为我没有正确阅读问题)。

是的,内存本身将在您的 sn-p 中,因为您已通过 make_shared 调用为控制块和对象分配了一个块。

【讨论】:

  • @Dmitriano 我最初确实误读了这个问题,所以现在编辑了我的答案。
  • 通常情况下,std::make_shared 为对象同时拥有控制块和空间是件好事。但是在某些情况下(例如许多长寿命的弱指针和寿命较短​​的强共享指针),闲置控制块的开销是可以接受的,但对象的闲置空间不是,然后故意不使用 std::make_shared 并做两件事-阶梯式方法是一种合理的选择。
  • @Eljay 我还没有看到weak_ptr 使代码更好、更容易推理的设计。即使单独使用 shared_ptr 也很少(尽管有时!)是合适的,但与 weak_ptr 结合使用它会成为代码维护者的噩梦。
  • 为什么shared_ptr 在这种情况下只为控制块重新分配,这不能解决?这是否被视为一个不值得的利基市场?
  • @bloody 我看不出在这种情况下如何使用 realloc。所有持有指向控制块的指针的对象都需要以某种方式通知控制块指针的变化,并且没有这样做的机制。从逻辑上讲,这与分配新的控制块是一样的——现有的对象不会知道它发生了。
【解决方案2】:

std::make_shared&lt;T&gt;() 分配一个包含构造的T 实例的控制块,然后返回引用该块的std::shared_ptr。当没有更多的std::shared_ptrs 引用控制块时,T 实例被破坏,但控制块本身不会被释放,直到没有更多的std::shared_ptrs 或std::weak_ptrs 引用它。在此示例中,当 main() 退出时,wpp 都超出范围:

#include <memory>

int main()
{
    auto p = std::make_shared<int>(5);
    
    std::weak_ptr<int> wp = p;
    
    p = nullptr; // <-- the int is destroyed here
    
    return wp.lock() == nullptr ? 0 : 1;
} // <-- the control block is freed here when p and wp are destroyed

【讨论】:

    猜你喜欢
    • 2014-06-24
    • 2014-09-12
    • 2021-10-15
    • 1970-01-01
    • 2010-12-04
    • 2015-03-29
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多