patterncppCritical
C++11 rvalues and move semantics with return statement
Viewed 0 times
withreturnstatementmoveandsemanticsrvalues
Problem
I'm trying to understand rvalue references and move semantics of C++11.
What is the difference between these examples, and which of them is going to do no vector copy?
First example:
Second example:
Third example:
What is the difference between these examples, and which of them is going to do no vector copy?
First example:
std::vector return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return tmp;
}
std::vector &&rval_ref = return_vector();Second example:
std::vector&& return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector &&rval_ref = return_vector();Third example:
std::vector return_vector(void)
{
std::vector tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector &&rval_ref = return_vector();Solution
First example
The first example returns a temporary which is caught by
except that in my rewrite you obviously can't use
Second example
In the second example you have created a run time error.
Third example
Your third example is roughly equivalent to your first. The
The best way to code what you're doing is:
Best practice
I.e. just as you would in C++03.
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.Second example
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.Third example
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:
Best practice
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.Code Snippets
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> &&rval_ref = return_vector();const std::vector<int>& rval_ref = return_vector();std::vector<int>&& return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> rval_ref = return_vector();Context
Stack Overflow Q#4986673, score: 677
Revisions (0)
No revisions yet.