C++ 释放嵌套容器和对象的内存

C++ freeing memory of nested container and objects

这个问题很有可能是重复的,但我不确定如何对此进行适当的搜索。这对你来说可能是微不足道的,但它对我这个初学者有很大帮助!

假设我有三个 classes,每个都有一个容器

class A {
    std::map<int, B> container1;
};

class B {
    std::unordered_map<int, C> container2;
};

class C {
    std::vector<int> container3;
};

如果我有一个从 class A 创建的对象 'a',其中 container1/2/3 全部填充了数据,我的问题如下:

  1. 当我调用a.container1.clear()时,分配给container2和container3的内存会全部释放吗?如果是这样,C++ 是如何做到这一点的?
  2. 调用'a'的析构函数时,container2和3会被释放吗?
  3. 如果 1 和 2 为真,它们是否适用于容器的任何嵌套组合?例如这里我有 map->unordered_map->vector。不同的组合可以是 vector->unordered_map->map.

我的直觉是它们都是真的。否则,如果我有一个非常深嵌套的结构,一直到底部并显式释放那里的内存是没有意义的。

简短的回答:是的,这种情况下的所有嵌套容器都将释放内存。

长答案:让我们从头开始工作。

首先,我假设这些是结构而不是 classes(或者容器已经被声明 public);否则,a.container1.clear() 将无法编译,因为 container1 将是 a 的私有成员。但是,撇开这一点不谈:

当您调用 a.container1.clear() 时会发生什么?根据 https://www.cplusplus.com/reference/map/map/clear/,clear 方法从容器中删除所有元素,然后将其销毁。

所以,这意味着a.container1中的每个B类型的对象都将被销毁,即B的析构函数将被调用。

在 C++ 中,当 class 的对象被销毁时,class 的每个成员的析构函数在 class 的析构函数完成后被调用(在此在这种情况下,B 的析构函数是默认的编译器生成的析构函数,因为不存在用户提供的析构函数)。所以,当B被销毁后,B.container2的析构函数就会被调用。由于 container2 是一个 unordered_map,它的析构函数将销毁它包含的所有元素 (https://www.cplusplus.com/reference/unordered_map/unordered_map/~unordered_map/)

由于 container2 的元素是 C 类型的,因此 container2 中的每个 C 类型的元素都将调用其析构函数。同样,将调用 container3 的析构函数。并且,作为一个向量,container3 的存储容量将被释放,即释放 (https://www.cplusplus.com/reference/vector/vector/~vector/).

现在,我们一直走到底部,我们看到所有内存都被释放了!