George H George H - 2 months ago 6
C++ Question

Smart pointer for holding forward references to objects

Assume I have this header:

#include <vector>

class B;

class A
{
...
private:
std::vector<what_pointer B> holder;
};


I don't want to include B in the header so I made the "class B" forward reference to it. However the header has that container for B's, and since B's true header is only included in the Cpp, I must use pointers to B inside the container.

Obviously I could create a destructor for A which goes through the "holder" and de allocates all the memory areas the pointers are pointing to. But I'm wondering if there is a smart pointer that "should" be used in this situation instead of a raw pointers.

Answer
  • In c++17, you may simply do

    class B;
    
    class A
    {
    public:
    ...
        ~A(); // define in cpp, as B definition should be known for destruction
    private:
        std::vector<B> holder;
    };
    

    as incomplete types would be allowed for vector.

  • Currently, you may do

    class A
    {
    public:
        //...
        A(const A&); // should be reimplemented to copy holder
        A& operator =(const A&); // should be reimplemented to copy pimpl
        A(A&&) = default;
        A& operator =(A&&) = default;
    
        ~A();
    private:
        std::vector<std::unique_ptr<B>> holder;
    };
    

    And then

    #include "B.h"
    
    // define in cpp, as B definition should be known
    ~A::A() = default;
    
    A::A(const A& rhs) {
        for (const auto& b : rhs.holder) {
             holder.push_back(std::make_unique<B>(*b));
        }
    }
    
    // ...
    
  • Or use pimpl idiom completely

    class A
    {
    public:
        //...
        A(const A&); // should be reimplemented to copy pimpl
        A& operator =(const A&); // should be reimplemented to copy pimpl
        A(A&&) = default;
        A& operator =(A&&) = default;
    
        ~A();
    private:
        struct Pimpl;
        std::unique_ptr<Pimpl> pimpl;
    };
    

    And then

    #include "B.h"
    
    struct A::Pimpl {
        // ...
        std::vector<B> holder;
    };
    
    // define in cpp, as B definition should be known
    ~A::A() = default;
    
    A::A(const A& rhs) : pimpl(std::make_unique<Pimpl>(rhs.pimpl)) {}
    
    // ...
    
Comments