Answers:
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
它既不是本地自动值也不是临时右值。现在,ref-qualifier &&
表示在rvalue临时对象上调用了第二个函数,进行了以下移动,而不是复制
Beta_ab ab = Beta().getAB();
例如,在有些不同的情况下,它可以更有效:
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
。
for(:)
并在已释放对象上进行了集成。修复:ideone.com/tQVOal
std::move()
仅用作显式表述,以更清楚地说明这一点。这不是您要复制粘贴到项目中的代码。它与最高投票答案没有矛盾,因为在函数内部创建了临时对象。这里返回的对象是参数之一(临时对象在评估(按词法包含)创建点的完整表达式的最后一步中被销毁)。