【问题标题】:Unwanted destruction in C++C++ 中不需要的破坏
【发布时间】:2014-11-22 03:32:41
【问题描述】:

我有以下代码:

class A;
typedef map<string, A*> AMap;
AMap _amap;

当我尝试分配一个新的 A 并将其保存到地图时:

A a = A(str);
_amap[str] = &a;

然后它会在我的程序结束之前调用A 的析构函数。 (我有一个 A 的静态成员来计数对象,当我想检查有多少对象时返回零)

但是,当我尝试时:

_amap[str] = new A(str);

一切正常,但没有调用析构函数。这是为什么呢?

这两种方法有什么区别?

谢谢。

更新

我之所以使用A*而不是A是因为我有另一个AList,它是一个向量,将存储同一个对象。我使用指针是因为我不想浪费内存。

【问题讨论】:

  • 前者添加一个自动变量的地址,后者是一个动态分配的变量。 动态分配它。这意味着您要么使用知道如何正确清理的智能指针来管理它,要么自己承担责任,就像你分配它一样
  • @WhozCraig 解释了为什么在第一种情况下调用析构函数?因为我不明白为什么。
  • 自动这个词是必不可少的。不管你是否知道,你剩下的就是一张带有悬空指针的地图。 IE。地图中的指针仍然存在,但只要 a 离开自动范围(周围的 {... } ),对象就会被销毁。如果您不知道,即使是评估,更不用说取消引用悬空指针会调用未定义的行为。下面的两个答案在如何管理这个问题上都是准确的,值得一提。请仔细阅读。
  • 有什么理由不使用map&lt;string, A&gt;?为什么是指针?
  • 之所以我使用A*而不是A是因为我还有另一个AList,它是一个向量,会存储同一个对象。我使用指针是因为我不想浪费内存。

标签: c++ class object memory-management constructor


【解决方案1】:

在第二种情况下,不会调用析构函数,因为您可能从未在堆上分配的 delete A 对象。

考虑使用以下 typedef:

typedef map<string, unique_ptr<A>> AMap;

然后,使用std::make_unique 创建对象:

_amap[str] = make_unique<A>(str);

(或者,在 C++14 之前:_amap[str] = unique_ptr&lt;A&gt;(new A(str));

std::unique_ptr 析构函数将确保堆分配的对象被删除,但请注意,这意味着当_amap 被销毁时,映射中的所有A 对象也将被销毁!

如果您有其他代码可能需要在_amap 的生命周期之外指向这些对象的指针,那么请考虑使用shared_ptr&lt;A&gt;(和make_shared&lt;A&gt;)。这些是共享所有权智能指针,只有在所有shared_ptr&lt;A&gt;实例被销毁时才会删除对象。

另一方面,如果您只需要A 对象存在某处,那么它们可以存在于地图中:

typedef map<string, A> AMap;

后来:

_amap.emplace(make_pair(str, A(str)));

【讨论】:

    【解决方案2】:

    在第一种方法中,您存储的是自动(“堆栈分配”)变量的地址,除非您知道地图本身在其值超出范围后将不会被使用,否则这不是一个好主意。

    在第二种方法中,您调用new,但从不调用delete,这当然是资源泄漏。

    而不是这两个,您应该将A 的实例直接存储在不带指针的映射中,或者如果您需要用于多态性的指针,则存储智能指针,以便在映射销毁期间发生值的销毁。

    【讨论】:

      猜你喜欢
      • 2011-06-11
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 2011-12-28
      相关资源
      最近更新 更多