-1

I just started learning smart pointer and came across a situation which seems to be contradicting with the theory. For e.g. When we use shared_ptr and if copy semantic is called the both the object shares the ownership and ref count is 2. This is okay and understood. code for example.

 class Test {
    public:
    Test(){ cout << "Const" << "\n"; }

    void Disp(){
        cout << "Class Test()\n";
    }

    ~Test(){ cout << "Dest" << "\n"; }
 };

int main()
{
 Test *p = new Test();
 shared_ptr<Test> p1(p);
 shared_ptr<Test> p2(p1); // = make_shared<Test>(*p1);

 p1->Disp();
 p2->Disp();

}

And output is fine as :

Const
Class Test()
Class Test()
Dest

Now if I try move semantic as

int main()
{
 Test *p = new Test();
 shared_ptr<Test> p1(p);
 shared_ptr<Test> p2 = make_shared<Test>(*p1);

 p1->Disp();
 p2->Disp();

}

Then p1 should have lost the ownership. Hence p1->Disp() should be valid. Because make_shared will transfer ownership as well as reset the p1. But still I can call p1->Disp() and the proper function is getting called. Please correct my understanding.

Thanks.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Nihal Kumar
  • 305
  • 3
  • 16
  • 3
    There is no move semantic in your second example, you are creating a new `Test` object – UnholySheep Jul 15 '21 at 19:58
  • Then what is the difference between example 1 and 2 because in both we are creating another shared_ptr from first shared_ptr object? Also, then in how can I call move semantics ? In which case the 1st pointer goes null after 2nd getting created ? – Nihal Kumar Jul 15 '21 at 20:03
  • 2
    In the first example you have a single instance of `Test` which both `shared_ptr` refer to. In the second one you have two instances of `Test` and each `shared_ptr` refers to a different one. – UnholySheep Jul 15 '21 at 20:04
  • Understood. can you please answer the 2nd and 3rd part of my first comment – Nihal Kumar Jul 15 '21 at 20:11
  • 1
    @NihalKumar You need to call the move constructor of `shared_ptr`, using `make_shared()` will not call that. And if you think about it, `make_shared(*p1)` **cant** move ownership from `p1`, because it doesn't know what `p1` is to steal ownership from it. `*p1` refers to the object that `p1` is holding a pointer to, it is not `p1` itself. – Remy Lebeau Jul 15 '21 at 21:01

1 Answers1

7

The main misunderstanding is that std::make_shared does not move ownership of the old object. Instead you are creating a second instance of Test which the new std::shared_ptr refers to.

If you really want to move ownership you need to do so explicitly, e.g.:

int main()
{
 Test *p = new Test();
 shared_ptr<Test> p1(p);
 shared_ptr<Test> p2(std::move(p1));

 // p1->Disp(); // No longer allowed, as p1 is now "empty"
 p2->Disp();
}
UnholySheep
  • 3,967
  • 4
  • 19
  • 24