这个问题在这里已有答案:
我正在用C ++测试我的知识并遇到了问题。考虑以下代码:
class A
{
public:
A(int n = 0)
: m_n(n)
{
std::cout << 'd';
}
A(const A& a)
: m_n(a.m_n)
{
std::cout << 'c';
}
A(A&& a){
std::cout<<'r';
}
private:
int m_n;
};
int main()
{
A a = A();
std::cout << std::endl;
return 0;
}
显然,A()构造函数是一个右值,因为没有创建永久对象。所以我认为首先我要看“d”作为输出。然后我们将rvalue复制到我们的新对象,该对象尚未初始化。我已经实现了一个复制构造函数,它接受一个rvalue作为参数,但我没有看到证据(没有“r”输出)。
有人可以解释为什么会这样吗?
您正在看到一种复制省略 - 编译器实际上需要通过直接使用构造函数表达式的参数(在本例中为A a = A()
)初始化a
来优化和实现()
,而不是创建临时的并将其复制到。如果要强制执行要复制的未命名对象,则需要使用不是简单构造函数调用的表达式初始化a
。
请注意,即使这样,编译器也可能通过as-if规则忽略construtor调用(如果唯一可见的副作用在复制/移动构造函数/析构函数中。最好的选择是“强制”调用移动ctor是使用一个命名值和std::move
:
A a1;
A a2 = std::move(a1);