0

Say, I have a class .h file named Ninja

I have two member functions and the default name is set to Ninja master and discple_ child is set to nullptr

Below is a snippit of the public/private of my class:

private:

    std::string name_;
    std::shared_ptr<Ninja> disciples_;


  public:
    Ninja(std::string name = "Ninja Master")
      : name_{name},
        disciples_{std::shared_ptr<Ninja>(nullptr)}
     {}
    ~Ninja() = default;     
Ninja(const Ninja& copy2);  //trying to make a copy constructor here
Ninja& operator=(const Ninja&);   // I also need help creating an assignment operator too 

I want to make a deep copy constructor but I am getting errors.

Below is the snippet for my deep copy constructor in the .cpp file.

Ninja::Ninja(const Ninja& copy2) {
   Ninja a();
   a = copy2; //error cannot convert const Ninja to Ninja() in assignment
}
  • This `Ninja a();` is a function declaration. A question asked a few minutes ago was having exactly the same problem! – Indiana Kernick Nov 21 '19 at 05:20
  • You can just write `Ninja a;` but I'm not sure why you're doing that – Indiana Kernick Nov 21 '19 at 05:22
  • ok I changed it to: name_ = copy2.name_; disciples_= copy2.disciples_; This gives no error, but I don't know if it's copying correctly – user10005002 Nov 21 '19 at 05:34
  • And, in the copy constructor, resist temptation to write `Ninja a = copy2` as - although it looks like an assignment - it actually calls the copy constructor. The result would therefore be infinite recursion. You might also want to question why a copy constructor should also create an object of the same type i.e. why should the copy constructor, which is called to initialise an instance of `Ninja`, create a second instance of `Ninja`? – Peter Nov 21 '19 at 05:35
  • Does this answer your question? [std::shared\_ptr deep copy object](https://stackoverflow.com/questions/19969260/stdshared-ptr-deep-copy-object) – Evg Nov 21 '19 at 05:53
  • Aside: `std::shared_ptr disciples_` is confusing. `std::shared_ptr` is zero or one `Ninja`s, "disciples" implies many. Perhaps you want `std::vector disciples_`? – Caleth Nov 21 '19 at 09:43

3 Answers3

1

Ninja a(); declares a function.

If you want to create a Ninja object, drop the parentheses : Ninja a;


The copy constructor could be implemented like this:

Ninja::Ninja(const Ninja &n)
:   name_(n.name_),
    disciples_(n.disciples_)
{
}
Sid S
  • 6,037
  • 2
  • 18
  • 24
0

An example of a deep copy constructor:

Ninja(const Ninja& other) 
    : name_(other.name_), 
      disciples_(other.disciples_ ? 
          std::make_shared<Ninja>(*other.disciples_) : 
          std::shared_ptr<Ninja>{}
      )
{}

It will create a new shared_ptr that will hold a copy of Ninja object managed by other.disciples_.

If you don't need a deep copy, just omit the copy constuctor. It will be implicitly defined and will make a copy of shared_ptr automatically.

I don't understand the usage of the ? ternary operator. Please explain.

We first check that shared_ptr stores a non-null pointer. If it does, we dereference it and create a new one using the copy constructor of Ninja, if it doesn't, we create an empty shared_ptr. If disciples_ is never empty by design, this check can be omitted.

Evg
  • 25,259
  • 5
  • 41
  • 83
  • 1
    Thank you, this works. I don't understand the usage of the ? ternary operator. Please explain – user10005002 Nov 21 '19 at 06:15
  • 1
    @user10005002 It basically ensures that your `shared_ptr` is not empty when you deference it (`*other.disciples_`). `std::unique_ptr` has a [conversion operator](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool) that converts it to a bool (true if and only if the pointer is not null) – ph3rin Nov 21 '19 at 06:23
  • @user10005002, added a few words. – Evg Nov 21 '19 at 06:32
0

You can do something like below -

  if( copy2.disciples_ )
    {   
        this->disciples_ = make_shared<Ninja>();
        this->disciples_->name_ = copy2.disciples_->name_;
        this->disciples_->disciples_= copy2.disciples_->disciples_;
    }   
    else
    {   
        this->disciples_ = copy2.disciples_;
    }   
Shrikant
  • 744
  • 8
  • 18