没有std :: move,如何通过值返回unique_ptr?

Ale*_*lex 9 c++ move-semantics copy-elision c++11

std::unique_ptr<int> ptr() {
    std::unique_ptr<int> p(new int(3));
    return p;  //  Why doesn't this require explicit move using std::move?
}  // Why didn't the data pointed to by 'p' is not destroyed here though p is not moved?

int main() {
    std::unique_ptr<int> a = ptr();  // Why doesn't this require std::move? 
    std::cout << *a; // Prints 3.
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,函数ptr()返回一个副本p.如果p超出范围,数据"3"应被删除.但是代码如何在没有任何访问冲突的情况下工作?

jua*_*nza 14

这在C++ 11标准第12.8/32节中阐述:

当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的 ....

(强调我的).用简单的英语来说,这意味着左值p可以被视为rvalue重载决策的时候,因为它是复制省略的候选者.这反过来意味着移动构造函数在重载决策时被拾取(事实上,移动副本可能无论如何都被省略了.)


rod*_*igo 6

由于return某些表达式(如本地自动变量)被明确定义为返回移动的对象(如果移动运算符可用).

所以:

return p;
Run Code Online (Sandbox Code Playgroud)

或多或少类似于:

return std::move(p);
Run Code Online (Sandbox Code Playgroud)

但请注意,这不适用于全局变量.

std::unique_ptr<int> g(new int(3));
std::unique_ptr<int> ptr() {
    return g;  //  error!!!
}
Run Code Online (Sandbox Code Playgroud)

  • @rodrigo"在具有类返回类型的函数的return语句中,当表达式是非易失性自动对象的名称(函数或catch子句参数除外),具有与函数相同的cv-unqualified类型返回类型,通过将自动对象直接构造为函数的返回值",可以省略复制/移动操作". (2认同)