2016-03-06 268 views
2

此代码编译成功。错误:这里声明unique_ptr(const unique_ptr&)= delete;

#include<iostream> 
#include<memory> 
using namespace std; 
class A{ 
     public: 
     unique_ptr<A> myval; 
     A(){ cout<<"Constrcutor of A is called"<<endl; } 
     ~A(){cout<<"Destructor of A is called"<<endl;} 
     unique_ptr<A> getsomething() 
     { 
       unique_ptr<A> myval; 
       myval.reset(new A); 
       return myval; 
     } 
}; 

但是当我评论本地unique_ptr<A> myval;编译器会抛出错误。

shared_test.cpp: In member function ‘std::unique_ptr<A> A::getsomething()’: 
shared_test.cpp:12:10: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = A; _Dp = std::default_delete<A>]’ 
    return myval; 
     ^
In file included from /usr/include/c++/4.8/memory:81:0, 
       from shared_test.cpp:2: 
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here 
     unique_ptr(const unique_ptr&) = delete; 
    ^

我无法理解这个错误的含义。它是什么?

+1

你明白为什么原始代码会编译吗?因为这也是一个有趣的问题,如果你不这样做,这个答案可能会很长。 – juanchopanza

回答

3

您的本地变量myval正在隐藏类成员myval

When the criteria for elision of a copy operation are met and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

在你的第一种情况下,利用作为myval如果它是一个rvalue创建返回的对象,因为它是一个rvalue,它允许选择move构造函数,如果有一个。

在第二种情况下,必须由一个副本,因此它直接调用copy构造,因为unique_ptr对象不能被复制到的失败,而你还没有使用std::move,以确保编译器调用构造函数move

+0

'myval'总是一个左值,而不是一个xvalue。有一个特殊的规则说,在这种情况下,您首先尝试重载解析,就好像对象是由右值指定一样,并不会改变这一事实。 –

+0

我已经更新了我的答案 – Jts

1

这意味着std::unique_ptr不能被复制。

让您return语句举动所有权,

return std::move(myval); 

或引用/指针回到原来的std::unique_ptr,虽然这将不转让所有权,是最有可能不是你想要的。

要理解为什么原来的OP代码的工作,看Returning unique_ptr from functions

编辑:我认为你的原身是这样的:

// .. 
unique_ptr<A> getsomething() 
     { 
       return myval; 
     } 

从您最初询问。

+0

那么,为什么要编译原始代码呢? – juanchopanza

+0

@juanchopanza谢谢,我已经添加了一个链接到解决这个问题的另一个问题,如果这就是你的意思 –

+0

是的,这就是我的意思。 – juanchopanza