#include <iostream>
struct X
{
X(const char *) { std::cout << 1; }
X(const X&) {std::cout << 2;} //copy ctor;
X(X&& ) {std::cout << 3;} //Move ctor;
};
X f(X a)
{
return a; //a will be moved out of f calling X's move ctor
}
X g(const char* b)
{
X c(b);
return c;
}
int main()
{
f("hello");
g("hello");
//prints 131 and not 1313
}
上面的程序输出是131为什么?根据我的理解,它应该是1313
即。当f返回移动构造函数在同一行上调用时,移动构造函数也应该在g返回时调用。
答案 0 :(得分:3)
欢迎来到ACCU 2014! : - )
在f
中,由于您要返回一个按值函数参数,因此可以隐式移动a
。
在g
中,由于您要返回本地自动存储变量,因此会c
隐式移动。
只有这些信息,那么你的理解是正确的:1313。如果编译器输出这个,它就会符合。
额外信息来自[class.copy] / p31,它描述了何时允许“返回值优化”(RVO)。 f
中不允许使用RVO,但g
允许使用RVO。确实没有充分的理由我知道f
中不允许使用RVO,除了我所知道的编译器没有找到如何实现它的事实。因此,没有动力改变规范以允许它。
我所知道的所有编译器都为g
实现了RVO,因此最终的移动结构被优化掉了 - 即使它有副作用。所以RVO不是“纯粹的优化”。因此,为了实现它,标准必须为此(可观察的)“优化”提供特殊许可。
答案 1 :(得分:2)
编译器可以优化代码并删除对复制构造函数的调用以返回对象。在C ++标准中甚至有一个特殊的例外允许这样做,因为这种优化改变了程序的可观察行为。搜索RVO(返回值优化)和NRVO(命名返回值优化)。一些编译器,例如msvc,即使在禁用优化时也会执行此操作。