我有以下代码:
class A;
typedef map<string, A*> AMap;
AMap _amap;
当我尝试分配新的A并将其保存到地图时:
A a = A(str);
_amap[str] = &a;
然后它会在我的程序结束之前调用A
的析构函数。 (我有一个静态成员用于计算对象,当我想检查有多少个对象时返回零)
然而,当我尝试:
_amap[str] = new A(str);
一切正常,但析构函数没有被调用。那是为什么?
这两种方法有什么区别?
感谢。
更新
我使用A*
代替A
的原因是我有另一个AList
,它是一个向量,将存储相同的对象。我使用指针因为我不想浪费记忆。
答案 0 :(得分:6)
在第二种情况下,不会调用析构函数,因为您可能永远不会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<A>(new A(str));
)
std::unique_ptr
析构函数将确保删除堆分配的对象,但请注意,这意味着当_amap
被销毁时,地图中的所有A
对象也将被删除!
如果您有其他代码可能需要在_amap
的生命周期之后指向这些对象,请考虑使用shared_ptr<A>
(和make_shared<A>
)。这些共享所有权智能指针只会在所有 shared_ptr<A>
个实例被销毁时删除该对象。
另一方面,如果你只需要A
个对象存在某个地方那么他们就可以生活在地图中:
typedef map<string, A> AMap;
后来:
_amap.emplace(make_pair(str, A(str)));
答案 1 :(得分:3)
在第一种方法中,您存储自动(“堆栈分配”)变量的地址,这不是一个好主意,除非您知道在其值超出范围之后不会使用地图本身。
在第二种方法中,您调用new
但不调用delete
,这当然是资源泄漏。
而不是这两个,你应该直接在地图中存储A
的实例而不指针,或者如果你需要指向多态的指针,那么存储智能指针,以便在破坏期间发生值的破坏。地图。