2

This codes compiles successfully.

#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;
        }
};

but when I comment localunique_ptr<A> myval; compiler throws error.

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;
       ^

I am not able to understand what this error says. What is it?

Sreeraj Chundayil
  • 5,548
  • 3
  • 29
  • 68
  • 1
    Do you understand why the original code does compile? Because that is also an interesting question, and if you don't, the answer to this one could be quite lengthy. – juanchopanza Mar 06 '16 at 06:19

2 Answers2

3

Your local variable myval is hiding the class member 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.

In your first case, the returned object is created using myval as if it was an rvalue, and since it's an rvalue, it's allowed to choose the move constructor if there's one.

In the second case, a copy must be made so it directly calls the copy constructor, which fails since a unique_ptr object cannot be copied, and you haven't used std::move to make sure the compiler calls the move constructor.

Jts
  • 3,447
  • 1
  • 11
  • 14
  • `myval` is always an lvalue, not an xvalue. That there's a special rule saying that in that context you first try overload resolution as if the object were designated by an rvalue doesn't change that fact. – T.C. Mar 06 '16 at 07:22
1

This means that std::unique_ptr cannot be copied.

Make your return statement move ownership,

return std::move(myval);

or return a reference / pointer to the original std::unique_ptr, although this won't transfer ownership and is most likely not what you want.

To understand why the original OP code works, see Returning unique_ptr from functions

EDIT: I assume your original body was thus:

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

from what you originally asked.

Community
  • 1
  • 1
058 094 041
  • 495
  • 3
  • 6
  • @juanchopanza Thanks, I've added a link to another question which tackles that issue, if that's what you mean – 058 094 041 Mar 06 '16 at 06:37
  • Yes, that is what I meant. – juanchopanza Mar 06 '16 at 06:46
  • since the return value is a temporary object that will be destroyed as soon as the function exits, thus guaranteeing the uniqueness of the returned pointer- I think this is the answer I am looking for, got from the SO link you gave. – Sreeraj Chundayil Mar 06 '16 at 07:01