#include <string> #include <vector> using namespace std; auto f() { vector<string> coll{ "hello" }; // // Must I use move(coll[0]) ? // return coll[0]; } int main() { auto s = f(); DoSomething(s); }
我知道:如果我只是返回coll,那么coll保证在返回时被移动.
不过,我不确定:coll [0]是否也保证在返回时被移动?
更新:
#include <iostream> struct A { A() { std::cout << "constructed\n"; } A(const A&) { std::cout << "copy-constructed\n"; } A(A&&) { std::cout << "move-constructed\n"; } ~A() { std::cout << "destructed\n"; } }; struct B { A a; }; A f() { B b; return b.a; } int main() { f(); }
gcc 6.2和clang 3.8输出相同:
constructed
copy-constructed
destructed
destructed
解决方法
In the following copy-initialization contexts,a move operation might@H_403_30@ be used instead of a copy operation:
If the expression in a return statement ([stmt.return]) is a (possibly parenthesized) id-expression that names an object with@H_403_30@ automatic storage duration declared in the body or@H_403_30@ parameter-declaration-clause of the innermost enclosing function or lambda-expression,or
[…]
overload resolution to select the constructor for the copy is first@H_403_30@ performed as if the object were designated by an rvalue. If the first@H_403_30@ overload resolution fails or was not performed,or if the type of the@H_403_30@ first parameter of the selected constructor is not an rvalue reference@H_403_30@ to the object’s type (possibly cv-qualified),overload resolution is@H_403_30@ performed again,considering the object as an lvalue.
b.a和coll [0]都不是id表达式.所以没有隐含的动作.如果你想要一个举动,你必须明确地做.