C++类变量析构函数 我有一个关于C++中类变量和作用域的问题。假设我有以下课程: class TestClass { public: std::vector<int> v; void foo() { v = std::vector<int>(10); } }

C++类变量析构函数 我有一个关于C++中类变量和作用域的问题。假设我有以下课程: class TestClass { public: std::vector<int> v; void foo() { v = std::vector<int>(10); } },c++,scope,C++,Scope,什么时候调用分配给v的向量的析构函数?它是在foo返回时调用还是在c超出范围时调用?v=std::vector10 创建临时对象,然后将C++11复制或移动到v中。在这一行之后,调用临时对象的析构函数 当c超出范围时,调用c.v的析构函数 注意:您也可以这样做 v、 调整尺寸10 v=std::vector10 创建临时对象,然后将C++11复制或移动到v中。在这一行之后,调用临时对象的析构函数 当c超出范围时,调用c.v的析构函数 注意:您也可以这样做 v、 调整尺寸10 调用TestClas

什么时候调用分配给v的向量的析构函数?它是在foo返回时调用还是在c超出范围时调用?

v=std::vector10

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

当c超出范围时,调用c.v的析构函数

注意:您也可以这样做

v、 调整尺寸10

v=std::vector10

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

当c超出范围时,调用c.v的析构函数

注意:您也可以这样做


v、 调整尺寸10

调用TestClass对象析构函数时,将调用成员向量的析构函数。当TestClass对象超出范围时会发生这种情况

{
  TestClass c;
  c.foo();
} // destructor for c calls destructor for v

这是因为C++标准10。 在非委托构造函数中,初始化在 顺序如下:

-首先,并且仅适用于大多数 派生类1.8,虚拟基类按以下顺序初始化 它们出现在定向对象从左到右的深度优先遍历上 基类的非循环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表

-然后,在中初始化直接基类 在基本说明符列表中显示的声明顺序 无论mem初始值设定项的顺序如何

-然后,非静态 数据成员按照在中声明的顺序初始化 再次定义类,而不考虑 mem初始化器

-最后,对 构造函数体被执行。11[注:申报顺序为: 其任务是确保在中销毁基本子对象和成员子对象 初始化的相反顺序。-结束注释]


在v=std::vector10行中,还将调用临时对象的析构函数,因为创建临时向量std::vector10只是为了初始化v,然后将其销毁。

调用TestClass对象析构函数时,将调用成员向量的析构函数。当TestClass对象超出范围时会发生这种情况

{
  TestClass c;
  c.foo();
} // destructor for c calls destructor for v

这是因为C++标准10。 在非委托构造函数中,初始化在 顺序如下:

-首先,并且仅适用于大多数 派生类1.8,虚拟基类按以下顺序初始化 它们出现在定向对象从左到右的深度优先遍历上 基类的非循环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表

-然后,在中初始化直接基类 在基本说明符列表中显示的声明顺序 无论mem初始值设定项的顺序如何

-然后,非静态 数据成员按照在中声明的顺序初始化 再次定义类,而不考虑 mem初始化器

-最后,对 构造函数体被执行。11[注:申报顺序为: 其任务是确保在中销毁基本子对象和成员子对象 初始化的相反顺序。-结束注释]


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

好的,让我们一步一步地完成这个步骤:

c是构造的,v是c的一个成员,所以v也必须构造。 福被称为 v被指定一个新值。新值被构造,旧v被破坏,临时向量被移动到v上。然后移动或复制到v。 富回报 c超出了范围 c被破坏,因此v也被破坏。
所以,当c被破坏时,v被破坏两次。如果我们没有移动构造函数,临时函数也可能会被破坏。

好的,让我们一步一步地完成这个步骤:

c是构造的,v是c的一个成员,所以v也必须构造。 福被称为 v被指定一个新值。新值被构造,旧v被破坏,临时向量被移动到v上。然后移动或复制到v。 富回报 c超出了范围 c被破坏,因此v也被破坏。
所以,当c被破坏时,v被破坏两次。如果没有移动构造函数,临时变量也可能会被析构函数破坏。

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

在赋值v时调用一次,在c超出范围时调用一次。@Ben您的第一条语句错误-将调用v的运算符,而不是析构函数。这就是你应该始终遵循三法则的原因之一。我认为Ben的意思是,在临时变量被分配给v的那一行之后调用析构函数。我也不明白三的规则在这里有什么作用?@NeilKirk分配给一个对象不会调用它的析构函数,但分配运算符-根据我的经验,这是很多人在不熟悉三的规则时感到困惑的一个原因。有一次,当你分配v时,当c超出范围时,@Ben您的第一条语句错误-将调用v的运算符=而不是析构函数。这就是你应该始终遵循三法则的原因之一。我认为Ben的意思是,在临时变量被分配给v的那一行之后调用析构函数。我也不明白三的规则在这里有什么作用?@NeilKirk分配给一个对象不会调用它的析构函数,但赋值运算符-根据我的经验,这是很多人在不熟悉三的规则时感到困惑的一个原因。旧v被破坏了-不,不是。赋值将导致调用vector::operator=,但不会调用它的析构函数。现在有了移动语义,旧的guts将在临时中结束,它将被销毁,因此效果是一样的-仍然,在赋值过程中,V的析构函数肯定不会被调用。那么我们什么时候销毁旧的V?永远不要记住,向量只是动态分配内存的包装器。这意味着内部内存当然会在赋值/移动过程中被破坏,但对象v本身只有在c超出范围时才会被破坏,这对我来说仍然没有意义。破坏v的内存和对象本身有什么区别?为什么你要把任务分派到一起,当他们做完全不同的事情时,C++?嗯,有一种方法可以避免重复:复制和交换习惯用法,如中所述。old v被破坏了-不,不是。赋值将导致调用vector::operator=,但不会调用它的析构函数。现在有了移动语义,旧的guts将在临时中结束,它将被销毁,因此效果是一样的-仍然,在赋值过程中,V的析构函数肯定不会被调用。那么我们什么时候销毁旧的V?永远不要记住,向量只是动态分配内存的包装器。这意味着内部内存当然会在赋值/移动过程中被破坏,但对象v本身只有在c超出范围时才会被破坏,这对我来说仍然没有意义。破坏v的内存和对象本身有什么区别?为什么你要把任务分派到一起,当他们做完全不同的事情时,C++?嗯,有一种方法可以避免重复:复制和交换习惯用法,例如中描述的。