c ++函数之后立即调用析构函数

时间:2018-06-03 12:01:57

标签: c++ c++11

在第一个main中,我们将调用复制构造函数来初始化两个对象c和d。然后我们将在我的类中调用first =运算符,然后为两个对象调用析构函数两次,输出为I4I5c5d5d5

对于第二个main,我们调用默认构造函数,然后调用构造函数的副本为5,然后我们在我的类中调用第二个运算符,在第二个运算符的末尾调用析构函数。

我不明白为什么在第一个operator =使用运算符后没有调用析构函数,为什么在第二个operator =使用第二个运算符后立即调用析构函数。

#include <iostream>

using namespace std;

class C {

  int i;

 public:


   C() : i(0)                  { cout << "D" << i; }

   C(int _i) : i(_i)           { cout << "I" << i; }

   C(const C& _c) : i(_c.i)    { cout << "C" << i;  }

   C& operator= ( const C& _c) { i = _c.i; cout << "c" << i; return *this; }

   C(C&& _c) : i(_c.i)         { cout << "M" << i; _c.i = 0; }

   C& operator= (C&& _c)       { i = _c.i; cout << "m" << i; _c.i = 0;
                                return *this; }

   ~C()                        { cout << "d" << i;  }
};


int main() {

  C c = 4;
  C d = 5;
  c = d;
}

/* int main() {
  C c;
  c = 5;
  } */

2 个答案:

答案 0 :(得分:2)

c = 5;行中,没有任何赋值运算符可以使用int,因此将创建一个临时C(5),然后在赋值中使用。

然后在声明结尾处销毁此临时表。

答案 1 :(得分:1)

第一版

最后一个析构函数调用与c = d;无关。

他们被调用是因为cd超出了范围,因此他们被销毁了,所以让我们从结果中删除它们,这给了我们:

I4I5c5

第一个I4I5分别是由语句= 4= 5构造的对象,它们是由接受{{1}的构造函数创建的无名临时对象}。

但是等等,如果我们将intc分配给临时工,为什么我们的d被调用?

这是因为复制省略。允许编译器完全消除这里的移动,即使它有副作用,它只是构建对象。代码相当于:

C& operator= (C&& _c)

然后,最后一个,C a {4}; C b {5}; 只是因为c5

第二版

对于第二个版本,不允许使用此省略,因为我们不会立即构建对象.. c = d; vs C c = 5;。因此,为C c; c = 5;创建的临时调用move-assignment运算符,然后在运算符返回后立即销毁。