当对象a
被破坏时,personsInHouse
地图是否也被破坏,或者我需要在析构函数中销毁它?如果我不这样做会造成内存泄漏吗?
class A {
public:
map<unsigned int, unsigned int> personsInHouse;
};
int main(){
A a;
A.hash[10] = 23;
};
答案 0 :(得分:5)
personsInHouse
的生命周期自动,因为您将按值存储,其生命周期是父对象的生命周期。因为您通过值创建a
,所以当它超出范围时会调用它的析构函数,并且对象的析构函数会自动调用它包含的对象的析构函数。因此,您不需要销毁personsInHouse
,就像您不需要销毁a
一样。
如果personsInHouse
是指针并且您使用map<unsigned int, unsigned int>
在动态存储空间中创建了new
并存储了指针在personsInHouse
中,您需要通过personsInHouse
手动释放A
在delete
的析构函数中指向的内存。但是在您发布的代码中并非如此。
您所做的是做到这一点的好方法:更喜欢按值存储您可以使用的每个对象,这样您就不必担心动态对象的生命周期管理。
答案 1 :(得分:4)
是的,确实如此。运行类的析构函数时,将运行其所有成员的析构函数。确切地说,订单是:
一般情况下,如果你没有指针,你也可以期望没有内存泄漏。情况并非总是如此:您可能正在使用泄漏函数,或者某些函数可能正在执行动态分配,然后返回对该对象的引用。使用智能指针可以进一步改善这种情况。
在C ++中避免内存泄漏的一种有用技术是RAII:所有标准容器都遵循它,这就是为什么在容器超出范围之前不需要显式clear()
容器。基本原则是让类在其析构函数中清理所有资源,然后为其创建专用类,以便大多数类不必担心它。
请注意,“类成员”是在类范围内定义的严格非静态成员。如果你有
struct S {
int* p;
};
然后p
是S
的唯一成员,当S
超出范围时,p
将被销毁(通常不会涉及任何事情,除了可能调整堆栈指针之外)。如果您在某个时间点S s; s.p = new int;
,那么p
仍然是唯一的成员,p
指向的对象将不为一个,因此s
超出范围时不被销毁。要实现这一点,您需要手动执行delete s.p;
,这与每个new
的一般规则相对应,需要具有相应的delete
(new[]
的同一性{和} { {1}})。