为什么我的析构函数被调用两次
Why is my destructor called twice?
假设我用以下方法给一个班级学生:
Student Student::method(Student x)
{
//nothing important
return x;
}
复制构造函数被调用两次,一次是在对象 x 作为参数发送时调用,第二次是在从函数返回 x 时调用。
当我调用此方法时,为什么以及何时调用类 Student 的析构函数两次?调用是这样的:a = b.method(c),其中 a、b 和 c 是 Student 对象。
对于您的示例,a = b.method(c);
,除了复制省略之外,可能会发生三个副本。第一种是将c
对象复制到函数参数 x
中。第二个是从函数返回x
对象时。第三种是将返回值复制到a
对象中时。前两个涉及复制构造函数,最后一个涉及复制赋值运算符,除非您将其更改为 Student a = b.method(c);
,在这种情况下,它们都使用复制构造函数。
a
、b
和c
都将在其范围结束时被摧毁。对象x
将在method
函数结束时销毁。函数的返回值将在包含它的完整表达式的末尾销毁 - 也就是说,一旦a = b.method(c);
完成。
但是,并非所有这些副本都必须发生 - 在某些情况下,编译器可以省略或省略类的复制/移动构造。将发生函数参数的第一次复制。在尝试复制函数之前,函数的第二个副本将首先被视为移动。可以省略此复制或移动。如果使用复制赋值,则最终副本(从临时返回值到 a
)将发生,但如果使用复制构造函数(如 Student a = b.method(c);
所示),则可能会被省略。
如果构造了两个 Student 对象,则必须销毁它们。复制到参数和从返回值中复制需要销毁。
当函数返回时(x
复制到返回值之后),将调用 x
的析构函数。
析构函数在包含函数调用的完整表达式的末尾调用(除非返回值通过分配给引用而延长其生存期)。
构建的每个具有自动存储持续时间的对象都将自动销毁(通常以相反的构造顺序)。你构造两个对象(x
和返回值),因此有两个析构函数调用。
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- C++析构函数调用两次,堆栈分配的复合对象
- Qt插槽调用了两次
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 调用一个小函数两次(例如在if条件和主体中)比将结果存储在局部变量中更可取
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 插槽调用了两次qt
- 调用某个回调函数两次会导致分段错误:Nan
- 基于 MFC 对话框的应用程序无法调用对话框两次
- 重载运算符 new(),为什么构造函数被调用两次?
- 当 reset() 被unique_ptr调用两次时会发生什么?
- 为什么在C 中超载邮政增量运算符两次调用构造函数
- 现代C++编译器是否能够避免在某些条件下两次调用常量函数
- 如果我对async_read进行两次调用,那么只有在处理完第一次调用之后,才会处理第二次调用,这是否安全
- 如何正确地将对象添加到向量,而无需两次调用析构函数
- boost::asio vs. libpcap:避免两次调用关闭
- 为什么 DNSServiceProcessResult 两次调用我的回调
- 在资源管理器左窗格上两次调用Windows 7外壳扩展dll Initialize方法
- 通过连续两次调用boost::asio::read来检索正确的数据