【问题标题】:Does wrapping a pointer in shared_ptr guarantee it will be deleted if I continue to use the raw pointer?在 shared_ptr 中包装一个指针是否保证如果我继续使用原始指针它将被删除?
【发布时间】:2021-07-23 08:32:45
【问题描述】:

我有一个在运行时生成的哈希表,由全局变量填充。

inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();

std::map<A*, int> createMap() {
     return std::map<A*, int>({{global1, 1}, {global2, 2}, {global3, 3}});
}

我想在运行时向map 添加新条目,这意味着我必须创建指向A 的新指针。

void doStuff(std::map<A*, int>& map) {
    A* runTimeValue = new A();
    map[runTimeValue] = 4;
}

但是,这会导致程序出现内存泄漏,因为当映射对象最终超出范围并被删除时,我将不得不担心删除 runTimeValue。我考虑将地图切换到std::map&lt;std::shared_ptr&lt;A&gt;, int&gt;,但使用std::shared_ptr&lt;A&gt; 很困难,因为它有许多不同的子类。

我的一个解决方案是将runTimeValue 包装在一个 shared_ptr 中,以便它可以自动删除,然后继续使用原始指针。

void doStuff(std::map<A*, int>& map) {
    A* runTimeValue = new A();
    std::shared_ptr<A> temp(runTimeValue);
    map[runTimeValue] = 4;
}

这行得通吗?我是否需要存储对temp 的引用,直到地图超出范围?有没有更好的方法来处理全局和运行时指针的混合,其中运行时指针必须被删除但全局指针不需要?

编辑,正在使用的“程序”示例:

inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();

int main() {
    while(true) {
        std::map<A*, int> map = createMap();
        doStuff(map);
        doStuff(map);
        doStuff(map);
    }
}

【问题讨论】:

  • 只要确保doStuff 在返回之前从map 中删除runTimeValue
  • 使用由 smart pointer 管理的原始指针很好(并且正常)但 smart pointer 必须比原始指针寿命更长指针。你可能不想要std:shared_ptrthough,而是std::unique_ptr
  • 那不是很有趣。内联变量。以前从未见过或使用过其中之一。是时候做一些阅读了。
  • 你确定不能只做std::map&lt;A, int&gt;吗?
  • 似乎我对全局变量的病态仇恨使我对inline变量的存在和需求视而不见。我可能会在不使用它的情况下进入我的坟墓并感到满足,但很高兴知道如果我找到一个需要这样做的用例,我可以选择。

标签: c++ pointers smart-pointers


【解决方案1】:

您对此有点犹豫。你的提议不会有好的结果。假设您实际上需要指针映射...

如果地图拥有其中包含的对象的唯一所有权,请使用std::map&lt;std::unique_ptr &lt;A&gt;, int&gt;。如果它与代码的其他部分共享所有权,请使用std::map&lt;std::shared_ptr &lt;A&gt;, int&gt;

那么,不管怎样:

  • 对象在地图中仍然存在时不会意外消失

  • 当您从地图中删除对象时,它们将被清理(或它们的引用计数减少)

对于您的全局对象,您可以酌情使用std::make_uniquestd::make_shared 创建它们,而不是使用new。然后可以像管理其他所有内容一样管理它们。

【讨论】:

    【解决方案2】:

    不要那样做。

    如果您使用智能指针,请确保智能指针从一开始就“拥有”该内存。 C++ 喜欢 RAII 概念。

    我想你想要一个unique_ptr - https://en.cppreference.com/w/cpp/memory/unique_ptr

    也就是说,只是一个确保内存被删除的智能点。

    一般来说,总是使用智能指针而不是原始指针。这使所有权更加清晰。但是您可以在需要时将其公开为原始指针 (*A)。但是让智能指针清理它。

    【讨论】:

      猜你喜欢
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多