150

例如:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}
4

2 回答 2

287
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

这将返回一个悬空引用,就像左值引用案例一样。函数返回后,临时对象将被破坏。您应该Beta_ab按值返回,如下所示

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

现在,它正确地将临时Beta_ab对象移动到函数的返回值中。如果编译器可以,它将通过使用 RVO(返回值优化)完全避免移动。现在,您可以执行以下操作

Beta_ab ab = others.toAB();

并且它会将临时构造移动到ab中,或者执行 RVO 以完全省略移动或复制。我建议您阅读BoostCon09 Rvalue References 101,它解释了这个问题,以及 (N)RVO 如何碰巧与之交互。


在其他情况下,您返回右值引用的情况将是一个好主意。想象一下,您有一个getAB()经常临时调用的函数。让它为右值临时对象返回一个 const 左值引用并不是最佳选择。你可以这样实现

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

请注意,move在这种情况下不是可选的,因为ab既不是本地自动也不是临时右值。现在,引用限定符 &&表示第二个函数在右值临时对象上调用,进行以下移动,而不是复制

Beta_ab ab = Beta().getAB();
于 2009-07-12T19:54:27.897 回答
-1

可以更有效,例如,在稍微不同的上下文中:

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

作为一个有趣的观察,在我的机器上clang++ -O3为上面的代码生成 54 条指令,而为常规代码生成 62 条指令std::min。但是,-O0它会为上面的代码生成 518 条指令,而为常规代码生成 481 条指令std::min

于 2018-04-09T17:15:09.887 回答