为什么我的析构函数被调用了两次?

时间:2013-01-29 11:38:39

标签: c++ destructor

假设我使用以下方法学习班级学生:

Student Student::method(Student x)
{
    //nothing important
    return x;
}

复制构造函数被调用两次,一次是当对象x作为参数发送时,第二次是从函数返回x时。

为什么是类的析构函数当我调用此方法时,Student调用了两次? 调用如下:a = b.method(c),其中a,b和c是Student对象。

3 个答案:

答案 0 :(得分:3)

对于您的示例a = b.method(c);,可能会发生三个副本,除了复制省略。第一种是将c对象复制到函数参数x中。第二个是从函数返回x对象的时间。第三种是将返回值复制到a对象中。前两个涉及复制构造函数,最后一个涉及复制赋值运算符,除非您将其更改为Student a = b.method(c);,在这种情况下它们都使用复制构造函数。

abc都将在其范围的末尾被销毁。对象x将在method函数结束时销毁。函数的返回值将在包含它的完整表达式的末尾被销毁 - 也就是说,a = b.method(c);完成后。

但是,并非所有这些副本都必须出现 - 在某些情况下,允许编译器 elide 或省略类的复制/移动构造。将发生函数参数的第一个副本。在尝试复制之前,该函数的第二个副本将被视为先移动。可以省略此副本或移动。如果您正在使用复制分配,则会发生从临时返回值到a的最终副本,但如果您使用复制构造函数(如Student a = b.method(c);),则可能会被删除。

答案 1 :(得分:1)

如果构造了两个Student对象,则必须对其进行破坏。复制到参数和返回值之外需要破坏。

答案 2 :(得分:1)

函数返回时调用x的析构函数(在x复制到返回值之后)。

在包含函数调用的完整表达式的末尾调用返回值的析构函数(除非返回值的生命周期通过分配给引用而延长)。

构造的具有自动存储持续时间的每个对象将自动被破坏(通常以相反的构造顺序)。您构造了两个对象(x和返回值),因此有两个析构函数调用。