通过右值引用返回是否更有效?

例如:

Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
90838 次浏览
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右值引用101,它解释了这个问题,以及(N) RVO 是如何与之相互作用的。


在其他情况下,返回值引用的情况是一个好主意。假设您有一个 getAB()函数,您经常在临时函数上调用该函数。对于 rvalue 临时值,使其返回常量 lvalue 引用并不是最佳选择。你可以这样实现它

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

请注意,在这种情况下,move不是可选的,因为 ab既不是本地自动的,也不是临时的 rvalue。现在,参考资料限定词&&说第二个函数在 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条指令,而普通的 std::min生成62条指令。然而,对于 -O0,它为以上代码生成518条指令,而普通 std::min为481条。