Why does the copy constructor is not called?

132 Views Asked by At
#include <iostream>
#include <memory>

using namespace std;

class Init {
private:
    int x;
public:
    Init(int y) {
        x = y;
        cout << "default constructor called" << endl;
        
    }
    
    Init(std::shared_ptr<Init> z) {
        this->x = z->x;
        cout << "copy constructor called" << endl;
    }
};

int main()
{
    int k = 5;
    std::shared_ptr<Init> a = std::make_shared<Init>(k);
    std::shared_ptr<Init> b(a);

    return 0;
}

My expectation is to call both default and copy constructor, but only default constructor is called. What might be the issue??

The output is: default construcor called

1

There are 1 best solutions below

0
463035818_is_not_an_ai On BEST ANSWER

Copy constructing a shared pointer calls the copy constructor of the shared pointer. This std::shared_ptr<Init> b(a); is not constructing an Init. Instead it constructs a shared_ptr that shares ownership with a of the same Init instance. In your code only a single Init instance is created. Sharing ownership of one instance is the purpose of having multiple copies of a shared pointer.

Init(std::shared_ptr<Init> z) is not a copy constructor. A copy constructor is Init(const Init&) (which is also not used in your code).

It isnt obvious what you actually wanted to do, however, this is how you can create a second shared_ptr that manages the lifetime of a second Init instance which is copy constructed from the first:

#include <iostream>
#include <memory>

// better not using namespace std;

class Init {
private:
    int x;
public:
    Init(int y) : x(y){ // <--- use member initializer list for initialization
        std::cout << "default constructor called\n";
    }
    
    Init(const Init& other) : x(other.x) {   // <--- copy constructor
        std::cout << "copy constructor called\n";
    }
};

int main()
{
    int k = 5;
    std::shared_ptr<Init> a = std::make_shared<Init>(k);
    std::shared_ptr<Init> b = std::make_shared<Init>(*a);
  
    // return 0; // not needed here
}

output:

default constructor called
copy constructor called

Live Demo

PS: Init(int y) is not a default constructor. A default constructor is one that can be called without arguments, eg Int(int y=0) would be a default constructor.