关于赋值运算符的工作原理我不明白,请看一下这段代码:
#include <iostream>
using namespace std;
class foo
{
int val{};
public:
foo()
{
}
foo( int n )
{
val = n;
cout<<"Constructor"<<endl;
}
foo( const foo& f )
{
cout<<"Copy constructor, val "<<endl;
val = f.val;
}
foo( const foo&& f )
{
cout<<"Copy constructor -rvalue-"<<endl;
val = f.val;
}
foo operator+( const foo& other ) const
{
cout<<"Sum "<<endl;
foo foo2;
foo2.val = val + other.val;
return foo2;
}
foo& operator=( const foo& f )
{
cout<<"Assignment operator\n";
val = f.val;
return *this;
}
foo& operator=( const foo&& f)
{
cout<<"Assignment operator, r-value\n";
val = f.val;
return *this;
}
~foo() {}
};
int main()
{
foo a{1}, b{5}, c{4};
foo d;
d = a + b + c;
foo d2 = a + b + c;
return 0;
}
此应用程序的输出是:
Constructor
Constructor
Constructor
Sum
Sum
Assignment operator, r-value
Sum
Sum
我不清楚为什么第二个赋值不会触发赋值运算符。第一个赋值是在一个通过默认构造构造的对象上,然后一个普通的赋值操作是可见的,在第二个分配中,一个临时对象应该由编译器构建,然后分配给d2,但是没有任何打印可见。赋值运算符提供。为什么呢?
由于
答案 0 :(得分:3)
没有第二项任务,您的代码只有一项任务。这条线
foo d2 = a + b + c;
是复制初始化。
答案 1 :(得分:1)
为了效率,这个:
foo d2 = a + b + c;
(以及T n = expr
其中T
是具有非显式复制构造函数的类型)实际上是
foo d2(foo(a + b + c)); // can be optimized to foo d2(a + b + c)
<强>不强>
foo d2;
d2 = a + b + c;
这就是为什么你只在输出中看到一个作业。
你可以这样想:当变量已经存在时,就是它的赋值。当你创建一个新变量时,它是一个构造函数调用。
答案 2 :(得分:0)
您正在初始化d2
,而不是分配给它,因此不会调用赋值运算符。
答案 3 :(得分:0)
第一个是赋值,第二个是初始化。在这种情况下,允许编译器忽略在这种情况下可能发生的复制或移动操作。