0

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.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
George H
  • 412
  • 3
  • 6
  • 12
  • Yes, you should use smart pointers. What are you worrying about? – songyuanyao Sep 21 '16 at 06:38
  • http://www.cplusplus.com/reference/memory/shared_ptr/ – amchacon Sep 21 '16 at 07:06
  • 1
    `std::unique_ptr` seems even better, or just use *pimpl* idiom completely. – Jarod42 Sep 21 '16 at 07:40
  • `unique_ptr` if you want to mirror value semantics in the closest way. Just remember [that it has no copy-ctor](https://stackoverflow.com/questions/3283778/why-can-i-not-push-back-a-unique-ptr-into-a-vector). – Bartek Banachewicz Sep 21 '16 at 08:05
  • 2
    Note that in C++17, it would be allowed to use incomplete type in `std::vector` (and currently most compiler already support it even if it is pedantically UB). – Jarod42 Sep 21 '16 at 08:08

1 Answers1

1
  • 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)) {}
    
    // ...
    
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Could you explain why exactly I need to redefine the copy&move constructors ? Isn't the implementation you "redefined" exactly the default implementation anyway ? – George H Sep 21 '16 at 11:20
  • @GeorgeH: `std::unique_ptr` is not copy-able, so you have to implement the copy-constructor to be equivalent to the `vector` version. And if you use `std::shared_ptr` instead, the default copy is not what you want (you want new object, not shared references). – Jarod42 Sep 21 '16 at 11:37
  • I tried implementing this method, doesn't seem to work, maybe because I'm using a map instead of a vector and moving the pointer into a std::pair. It does seem to work using shared_ptr though ... is there any problem using that instead ? – George H Sep 21 '16 at 11:55
  • @GeorgeH: How is your `map` ? I suggest to use pimpl idiom BTW. – Jarod42 Sep 21 '16 at 12:08
  • std::map< std::string, std::shared_ptr > m_mymap; pimpl idiom seems to convoluted tbh, e.g. would not make for readable code. – George H Sep 21 '16 at 12:33