从C ++ 11开始,我们已经移动了语义。在下面的示例中,将使用move-constructor(或复制elision),而不是像C ++ 98中那样使用copy-constructor,而无需任何额外的工作。
std::string f()
{
std::string res;
...
return res; // <- move is used here instead of copy
}
但是这个案子呢?
std::string f()
{
std::optional<std::string> res;
...
return *res; // <-- will the std::string value be moved??
}
或者必须写这样的东西?
std::string f()
{
std::optional<std::string> res;
...
return *std::move(res);
}
答案 0 :(得分:5)
否即可。隐式移动的标准是[class.copy]:
当[...]或
return
语句中的表达式是(可能)时 括号内的 id-expression ,用于在主体中声明自动存储持续时间的对象或最内层封闭函数的 parameter-declaration-clause 或 lambda-expression < / em>,重载解析到 选择首先执行复制的构造函数,就像对象是由右值指定一样。
*res
不是 id-expression ,因此此规则不适用。如果要移出底层字符串,则必须明确地执行此操作:
return std::move(*res);
return *std::move(res);
return std::move(res).value(); // equivalent and possibly more legible
这些规则只有在绝对安全的情况下才能尝试更高效的选项。如果您要返回一个自动存储持续时间变量,那么移动它是完全安全的,因为没有别的东西会再次引用该变量。
但是,如果您要返回*res
,则不一定能安全离开。如果这给了你一些外部对象的参考,这将超过这个功能呢?我们将默默地从我们期望仍然有效的状态移动!在这种情况下,由用户决定是否要移动它。