xml*_*lmx 11 c++ standards move-semantics c++11
#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);
}
Run Code Online (Sandbox Code Playgroud)
我知道:如果我只是return 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();
}
Run Code Online (Sandbox Code Playgroud)
gcc 6.2和clang 3.8输出相同:
建造
拷贝构造
自毁
自毁
“隐式移动”规则的最简洁的表述位于当前工作论文的[class.copy.elision]/3中:
在以下复制初始化上下文中,可能会使用移动操作而不是复制操作:
如果return 语句 ([stmt.return]) 中的表达式是一个(可能带括号的) id 表达式,该 id 表达式命名具有在最内层封闭函数或lambda表达式的主体或 参数声明子句中声明的自动存储持续时间的对象, 或者
[...]
首先执行重载决策来选择副本的构造函数,就好像该对象是由右值指定的一样。如果第一次重载决策失败或未执行,或者所选构造函数的第一个参数的类型不是对象类型的右值引用(可能是 cv 限定的),则再次执行重载决策,并将该对象视为左值。
也不b.a是coll[0]id -expression。因此,并没有隐性的举动。如果你想要移动,你必须明确地这样做。