Search code examples
c++polymorphismunique-ptrvirtual-destructor

Vector of polymorphic objects and unique_ptr


I am trying to do an assignment and decided to properly manage memory this time but ended up with more questions than answers. I want to have a vector of children of a parent class for example vector<Parent> list, as far as I understand I need to use pointers to avoid slicing my objects so vector<Parent*>,

I then learned about smart pointers in c++ but also about the potential memory leak that happens if the destructor of the parent class is called (potentially by the smart pointers getting out of scope and whatnot). I don't know what the proper way to write my classes to avoid memory leaks is, I wrote an example of where I am at, this is printing "This is A" which I think means that if the destructor was to be called by the pointer it would cause a memory leak.

public:
    virtual void funct(){
        cout << "This is A" << endl;
    }
};
class B : public A{
public:
    void funct(){
        cout << "This is B" << endl;
    }
};

int main() {
    B b;

    auto ptr = make_unique<A>(b);

    ptr.get()->funct();

    return 0;
}

Taking things from the comments, would this be enough to not cause a memory leak, meaning if I delete the unique pointer ptr, would it free the memory allocated for B?

class A{
public:
    virtual void funct(){
        cout << "This is A" << endl;
    };
    virtual ~A() = default;
};
class B : public A{
public:
    void funct() override{
        cout << "This is B" << endl;
    }
    
    ~B() override = default;
};

int main() {
    B b;

    unique_ptr<A> ptr = make_unique<B>(b);

    ptr->funct();

    return 0;
}

Solution

  • To make sure the memory is released properly from a smart pointer (any allocated object really), you just need to make sure the base class destructor is marked virtual.

    class A
    {
    public:
        A() {}
        virtual ~A() = default;
        virtual void func() {};
    };
    
    class B : public A
    {
    public:
        B() {}
    };
    
    class C : public B
    {
    public:
        C() {}
        void func() override {}
    };
    
    auto obj = std::make_unique<C>();
    

    when obj goes out of scope, it will free memory properly. You dont even need specify the destructor in the other classes because they get default destructors already. the base needs to be marked virtual though, so thats why you need to specify the destructor in the base class.