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

Vic*_*nko 1 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
}
Run Code Online (Sandbox Code Playgroud)

但是这个案子怎么样?

std::string f()
{
    std::optional<std::string> res;
    ...
    return *res; // <-- will the std::string value be moved??
}
Run Code Online (Sandbox Code Playgroud)

或者一个人必须写这样的东西?

std::string f()
{
    std::optional<std::string> res;
    ...
    return *std::move(res);
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 5

.隐式移动的标准是[class.copy]:

当[...],或当表达在一个return语句是一个(可能是括号)ID-表达名称与所述主体或在声明的自动存储持续时间的对象参数声明子句的最内层的闭合功能或λ-表达,首先执行重载决策以选择副本的构造函数,就好像该对象是由rvalue指定的一样.

*res不是id-expression,因此该规则不适用.如果要移出基础字符串,则必须明确地执行此操作:

return std::move(*res);
return *std::move(res);
return std::move(res).value(); // equivalent and possibly more legible
Run Code Online (Sandbox Code Playgroud)

规则旨在尝试更有效的选项,只有在绝对安全的情况下.如果你要返回一个自动存储持续时间变量,那么移动它是完全安全的,因为没有别的东西会再次引用该变量.

但如果你要回来*res,那就不一定安全了.如果这给了你一些外部对象的参考,这将超过这个功能呢?我们将默默地从我们期望仍然有效的状态移动!在这种情况下,由用户决定是否要移动它.