1
votes

In below code snippet i am getting segmentation fault while passing unique_ptr as as value. usually this is known issue with auto_ptr as due to ownership issue (Assignee pointer becomes NULL) it can't be accessed after assignment. but why i am facing the same issue with unique_ptr even though it is having move semantics.

what i understood auto_ptr use copy constructor and unique_ptr use move function to transfer the ownership. But in both cases assignee pointer becomes null then what is the significance of having move semantics here. I believe compiler should flash the error if unique_ptr is passed as a value like below statement as copy constructor is private in unique_ptr. could you throw some light on this regarding this behaviour.

unique_ptr<Test> a = p;//deleted function (copy constructor).

Here is the code snippet:

#include<iostream>

#include<memory>

using namespace std;

class Test
{
public:
    Test(int a = 0 ) : m_a(a)
    {
    }
    ~Test( )
    {
        cout<<"Calling destructor"<<endl;
    }

    int m_a;
};


//***************************************************************
void Fun(std::unique_ptr<Test> p1 )
{
    cout<<p1->m_a<<endl;
}
//***************************************************************
int  main( )
{
    std::unique_ptr<Test> p( new Test(5) );
    Fun(std::move(p));
    cout<<p->m_a<<endl;

    return 0;
}
3
you may still access the same by passing reference . - user2907032
With unique_ptr and move, your have to be explicit about the ownership transfer. - Jarod42
In rust, similar code would produce compiler error :-) - Jarod42
and with unique_ptr ownership is handled compile-time. - Jens Munk
You are moving ownership of your object into the function (indicated by the explicit move), leaving the original pointer empty (nullptr) and then you dereference that pointer. What did you expect would happen and why are you passing a unique ptr into the function at all? A normal or would do just fine. - MikeMB

3 Answers

3
votes

By writing std::move(p) you are casting p to an r-value reference. unique_ptr has a constructor that takes an r-value reference (a move constructor) so it constructs the by-value parameter using this move constructor and there is no compilation error.

You should not pass a unique_ptr by value unless you want to transfer ownership.

If you transfer ownership then the unique_ptr in the outer scope does not own anything anymore and it is undefined behaviour to dereference it.

In this case you should pass Test by const reference:

void fun(const Test& t) {
    std::cout << t.m_a << std::endl;
} 

int main(){
    auto p = std::make_unique<Test>(5);
    fun(*p);
}

See here for more information about how to pass smart pointers in general.

1
votes

The deleted copy constructor is not involved here. unique_ptr has a move constructor which is used, because you explicitly requested a move from the source with std::move.

You shouldn't be using the moved-from value except to destroy it out assign to it.

It's not an error. A compiler could warn, but since you have explicitly moved it may reasonably assume that you know what you are doing.

0
votes

Instead of using unique_ptr as a value , pass the same as a reference . You create a unique pointer. You then construct another unique_ptr from that one, using the move constructor. So the original gets set to null. That's what happens when you move a unique_ptr. Honestly speaking as i didn't get chance work with auto_ptr so can't comment on this behavior.

void Fun( const std::unique_ptr<Test>& p1 )
{
 cout<<p1->ma;
}