c++shared-ptrsmart-pointerscopy-constructordefault-constructor

Why does the copy constructor is not called?


#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


Solution

  • 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.