0

Say that I have a class A and a class B which further has a subclass B1. Now I want to assign a pointer of B1 to be a member of A. I could do that by simply heap allocating B1 and then using delete in the destructor of A as follows:

class B {
    public:
        B() { };
};

class B1 : public B {
    public:
        B1() { };
};


class A {
    public:
         B* b_instance;

         A(B* b_instance){
             this->b_instance = b_instance;
         };

         ~A(){
             delete this->b_instance;
         };
};

int main() {
    B* b_instance = new B1();
    A a_instance(b_instance);
    return 0;
};

Now I believe another approach (and one that is more favored?) would use std::unique_ptr, whereby a unique_ptr to B1 is given to A and thus, as a smart pointer, whenever A is destroyed B1 is automatically destroyed as well since there are no more references to it. My best guess is that it should look something like this:

#include <memory>

class B {
    public:
        B() { };
};

class B1 : public B {
    public:
        B1() { };
};


class A {
    public:
         std::unique_ptr<B> b_instance;

         A(B& b_instance){
             this->b_instance = std::make_unique<B>(b_instance);
         };

         ~A(){ };
};

int main() {
    B1 b_instance;
    A a_instance(b_instance);
    return 0;
};

Is the unique_ptr approach the same as the approach outlined above so long as you remember to include delete this->b_instance in the destructor of A? Or are there other benefits of the unique_ptr approach?

Chris Gnam
  • 311
  • 2
  • 7
  • 3
    (1) If the constructor of `A` throws, then the d'tor will never be called and the resource could leak. (2) The default copy assignment c'tor of A is implicitly defined in your example, so you can do `A new = a_instance;` and end up double-freeing your resource. (3) If you have a unique_ptr defined then the default copy c'tor won't be created (unique_ptr can only be moved). – JohnFilleau Feb 07 '23 at 01:38
  • Note there are 5 methods in a class that can automatically be generated by the compiler (see rule of 3/5). If you are not careful in your original version the compiler generated methods could result in multiple `A` objects containing the same pointer, resulting in multiple deletes on the pointer. The use of `unique_ptr` will prevent this. – Martin York Feb 07 '23 at 04:02

1 Answers1

2

Is the unique_ptr approach the same as the approach outlined above so long as you remember to include delete this->b_instance in the destructor of A?

More or less.

Or are there other benefits of the unique_ptr approach?

Yes, you get automatic move semantics and copy semantics is turned off, greatly helping to prevent involuntary multiple owners of the same resource.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108