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

时间:2014-09-17 07:49:24

标签: c++ c++11 move-semantics copy-elision

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.
}

在上面的代码中,函数ptr()返回p的副本。当p超出范围时,数据&#39; 3&#39}应该被删除。但是代码如何在没有任何访问冲突的情况下工作?

2 个答案:

答案 0 :(得分:14)

这是在C ++ 11标准中提出的,§12.8/ 32

  

当符合或将要执行复制操作的标准时   因为源对象是一个函数参数这个事实,   并且要复制的对象由左值重载指定   首先执行选择复制的构造函数的分辨率   好像对象是由右值指定的 ....

(强调我的)。用简单的英语表示,当涉及到重载决策时,左值p可以被视为rvalue,因为它是 copy elision 的候选者。这反过来意味着移动构造函数在重载决策时被拾取(事实上,移动副本可能无论如何都会被删除。)

答案 1 :(得分:6)

因为某些表达式的return(例如本地自动变量)被明确定义为返回移动的对象,因此移动运算符可用。< / p>

所以:

return p;

或多或少类似于:

return std::move(p);

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

std::unique_ptr<int> g(new int(3));
std::unique_ptr<int> ptr() {
    return g;  //  error!!!
}