我不太了解C ++代码的一部分。 另外我不知道在哪里可以搜索有关它的信息,所以我决定提问。
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test();
Test(Test const & src);
Test& operator=(const Test& rhs);
Test test();
int x;
};
Test::Test()
{
cout << "Constructor has been called" << endl;
}
Test::Test(Test const & src)
{
cout << "Copy constructor has been called" << endl;
}
Test& Test::operator=(const Test& rhs)
{
cout << "Assignment operator" << endl;
}
Test Test::test()
{
return Test();
}
int main()
{
Test a;
Test b = a.test();
return 0;
}
为什么我得到的输入是
Constructor has been called
Constructor has been called
? a.test()通过调用“Test()”创建一个新实例,这就是显示第二条消息的原因。但为什么没有复制构造函数或赋值? 如果我将“return Test()”更改为“return *(new Test())”,则调用复制构造函数。
那为什么不是第一次叫它?
答案 0 :(得分:3)
编译器非常聪明。两份副本 - 从test
返回并初始化b
(不是这不是作业) - 根据以下规则(C ++11§12.8)被删除:
当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过直接构造临时对象来省略复制/移动操作进入省略的复制/移动目标
即使编译器会改变程序的行为(比如删除输出消息),也允许编译器执行此操作。预计您不会编写具有其他副作用的复制/移动构造函数和赋值运算符。
请注意,只有四种情况中的一种可以发生复制省略(不计算as-if规则)。
答案 1 :(得分:-2)
对a.test()的调用按值返回,然后将该值赋给b“复制”返回值。这将调用复制构造函数。