1

假设我有一个学生类的方法:

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

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

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

4

3 回答 3

3

对于您的示例,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);),则可能会被省略。

于 2013-01-29T11:52:07.263 回答
1

如果构造了两个 Student 对象,则必须将它们销毁。传入参数和传出返回值的副本需要破坏。

于 2013-01-29T11:39:36.120 回答
1

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

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

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

于 2013-01-29T11:39:45.407 回答