在第一个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;
} */
答案 0 :(得分:2)
在c = 5;
行中,没有任何赋值运算符可以使用int
,因此将创建一个临时C(5)
,然后在赋值中使用。
然后在声明结尾处销毁此临时表。
答案 1 :(得分:1)
第一版
最后一个析构函数调用与c = d;
无关。
他们被调用是因为c
和d
超出了范围,因此他们被销毁了,所以让我们从结果中删除它们,这给了我们:
I4I5c5
第一个I4
和I5
分别是由语句= 4
和= 5
构造的对象,它们是由接受{{1}的构造函数创建的无名临时对象}。
但是等等,如果我们将int
和c
分配给临时工,为什么我们的d
被调用?
这是因为复制省略。允许编译器完全消除这里的移动,即使它有副作用,它只是构建对象。代码相当于:
C& operator= (C&& _c)
然后,最后一个,C a {4};
C b {5};
只是因为c5
。
第二版
对于第二个版本,不允许使用此省略,因为我们不会立即构建对象.. c = d;
vs C c = 5;
。因此,为C c; c = 5;
创建的临时调用move-assignment运算符,然后在运算符返回后立即销毁。