一句話,直接返回即可,不用任何變化。
當啟動了c++11選項後,通過函數返回代碼沒有發生任何變化,但是已經使用了move語義,而不需要之前的NRVO編譯器優化技術。
注意,右值引用rvalue reference是表達式計算完成後就不再存在的臨時變量,左值是表達式計算完成後的變量。如果能夠用&求址的,就是左值。
下面是stackoverflow上的一個討論貼,比較有價值:
246down voteaccepted
std::vector return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return tmp;
}
std::vector &&rval_ref = return_vector();
The first example returns a temporary which is caught by rval_ref
. That temporary will have its life extended beyond the rval_ref
definition and you can use it as if you had caught it by value. This is very similar to the following:
const std::vector& rval_ref = return_vector();
except that in my rewrite you obviously can't use rval_ref in a non-const manner.
std::vector&& return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector &&rval_ref = return_vector();
In the second example you have created a run time error. rval_ref now holds a reference to the destructed tmp inside the function. With any luck, this code would immediately crash.
std::vector return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector &&rval_ref = return_vector();
Your third example is roughly equivalent to your first. The std::move on tmp is unnecessary and can actually be a performance pessimization as it will inhibit return value optimization.
The best way to code what you're doing is:
std::vector return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return tmp;
}
std::vector rval_ref = return_vector();
I.e. just as you would in C++03. tmp is implicitly treated as an rvalue in the return statement. It will either be returned via return-value-optimization (no copy, no move), or if the compiler decides it can not perform RVO, then it will use vector's move constructor to do the return. Only if RVO is not performed, and if the returned type did not have a move constructor would the copy constructor be used for the return.
shareeditflag answered Feb 13 '11 at 20:52Howard Hinnantreturn my_local;
. Multiple return statements are ok and will not inhibit RVO. – Howard Hinnant Feb 25 '13 at 20:18
3
There is a caveat: when returning a member of a local object, the move must be explicit. – boycy Feb 26 '13 at 8:58
4
@NoSenseEtAl: There is no temporary created on the return line. move
doesn't create a temporary. It casts an lvalue to an xvalue, making no copies, creating nothing, destroying nothing. That example is the exact same situation as if you returned by lvalue-reference and removed the move
from the return line: Either way you've got a dangling reference to a local variable inside the function and which has been destructed. – Howard Hinnant Feb 27 '13 at 16:11
1
upvote
flag
Just a nit: Since you named the variable (tmp
) in the "Best practice" section, it is the NRVO that kicks in, not the RVO. These are two different optimizations. Other than that, great answer! – Daniel Frey Feb
我在前幾天的程序中當用這種情況的時候返回vector