如果我继续使用原始指针,在 shared_ptr 中包装指针是否保证它会被删除?

Does wrapping a pointer in shared_ptr guarantee it will be deleted if I continue to use the raw pointer?

我在 运行 时生成了一个散列 table,由全局变量填充。

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<std::shared_ptr<A>, int>,但使用 std::shared_ptr<A> 很困难,因为它有许多不同的子类。

我的一个解决方案是将 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);
    }
}

不要那样做。

如果你使用智能指针,那么确保智能指针'owns'从一开始就是内存。 C++ 喜欢 RAII 概念。

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

也就是智能点保证内存被删除

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

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

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

然后,无论哪种方式:

  • 对象不会意外消失,同时仍然存在于您的地图中

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

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