返回类型和移动语义

时间:2014-04-11 07:54:24

标签: c++ c++11 move-semantics

#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返回时调用。

2 个答案:

答案 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,即使在禁用优化时也会执行此操作。