C++ 通过右值引用返回更有效吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1116641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:51:29  来源:igfitidea点击:

Is returning by rvalue reference more efficient?

c++c++11rvalue-reference

提问by Neil G

for example:

例如:

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

回答by Johannes Schaub - litb

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

This returns a dangling reference, just like with the lvalue reference case. After the function returns, the temporary object will get destructed. You should return Beta_abby value, like the following

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

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

Now, it's properly moving a temporary Beta_abobject into the return value of the function. If the compiler can, it will avoid the move altogether, by using RVO (return value optimization). Now, you can do the following

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

Beta_ab ab = others.toAB();

And it will move construct the temporary into ab, or do RVO to omit doing a move or copy altogether. I recommend you to read BoostCon09 Rvalue References 101which explains the matter, and how (N)RVO happens to interact with this.

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



Your case of returning an rvalue reference would be a good idea in other occasions. Imagine you have a getAB()function which you often invoke on a temporary. It's not optimal to make it return a const lvalue reference for rvalue temporaries. You may implement it like this

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

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

Note that movein this case is not optional, because abis neither a local automatic nor a temporary rvalue. Now, the ref-qualifier&&says that the second function is invoked on rvalue temporaries, making the following move, instead of copy

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

Beta_ab ab = Beta().getAB();

回答by wonder.mice

It canbe more efficient, for example, in a bit different context:

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

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;
}

As an interesting observation, on my machine clang++ -O3generates 54 instructions for code above versus 62 instructions for regular std::min. However, with -O0it generates 518 instructions for code above versus 481 for regular std::min.

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