I'm watching the "Don’t Help the Compiler" talk by STL, where he has the similar example on slide 26:
struct A
{
A() = default;
A(const A&) { std::cout << "copied" << std::endl; }
A(A&&) { std::cout << "moved" << std::endl; }
};
std::pair<A, A> get_pair()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple_moved()
{
std::pair<A, A> p;
return std::move(p);
}
With this, the following call:
get_pair();
get_tuple();
get_tuple_moved();
Produces this output:
moved
moved
copied
copied
moved
moved
Result of get_pair is move-constructed, which is as expected. A move may also has been completely elided by NRVO, but it is off the topic of the present question.
Result of get_tuple_moved is also move-constructed, which is explicitly specified to be so. However, result of get_tuple is copy-constructed, which is completely un-obvious to me.
I thought that any expression passed to return statement may be thought of as having implicit move on it, since the compiler knows it is about to go out of scope anyway. Seems like I'm wrong. Can someone clarify, what is going on here?
See also related, but different question: When should std::move be used on a function return value?
Aucun commentaire:
Enregistrer un commentaire