返回时隐式移动std :: optional中包含的值

时间:2016-07-27 15:28:13

标签: c++ move-semantics c++17

从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);
}

1 个答案:

答案 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,则不一定能安全离开。如果这给了你一些外部对象的参考,这将超过这个功能呢?我们将默默地从我们期望仍然有效的状态移动!在这种情况下,由用户决定是否要移动它。