C++类变量析构函数

C++ Class variable destructor

本文关键字:析构函数 类变量 C++      更新时间:2023-10-16

我有一个关于C++中类变量和作用域的问题。假设我有下面的课程:

class TestClass {
public:
    std::vector<int> v;
    void foo()
    {
        v = std::vector<int>(10);
    }
}

现在,假设我调用以下代码:

TestClass c;
c.foo();

向量(赋值给v)的析构函数什么时候调用?它是在foo()返回时调用还是在c超出作用域时调用?

调用TestClass对象析构函数时,将调用成员向量的析构函数。当TestClass对象超出范围时,就会发生这种情况
{
  TestClass c;
  c.foo();
} // destructor for c calls destructor for v

这是因为C++标准12.6.2§10:

在非委托构造函数中,初始化在以下顺序:

--首先,而且只适用于大多数构造函数派生类(1.8),虚拟基类按以下顺序初始化它们出现在有向的从左到右的深度优先遍历中基类的非循环图,其中"从左到右"是基类在派生类中的外观基说明符列表。

--然后,直接基类在中初始化在基说明符列表中出现的声明顺序(不管mem初始化程序的顺序如何)。

--然后,非静态数据成员按照在中声明的顺序进行初始化类定义(同样与mem初始化器)。

--最后构造函数主体被执行。11[注:申报顺序为被授权确保在中销毁基本子对象和成员子对象初始化的相反顺序--尾注]

v = std::vector<int>(10)行中,还将调用临时对象的析构函数,因为创建临时向量std::vector<int>(10)只是为了初始化v,然后它被销毁。

v = std::vector<int>(10);

创建临时对象,然后将其复制(或移动C++11)到v中。在这一行之后,将调用临时对象的析构函数。

c超出作用域时,会调用c.v的析构函数。

注意:你也可以做

v.resize(10);

好的,让我们一步一步地进行:

  • c是构造的,v是c的成员,所以v也必须构造
  • foo被调用
  • v被赋予一个新的值。构造新值,破坏旧v,将临时向量移动到v上。然后移动或复制到v中
  • foo返回
  • c超出范围
  • c被破坏,因此v也被破坏

因此,当c被破坏时,v被破坏两次。如果我们没有移动构造函数,临时的可能也会被破坏。

当您的变量c超出范围时,析构函数会自动为c调用,而c是自动分配的,该析构函数将负责删除向量