2

I have a class setup analogous to this:

class BlimpBase{
public:
    virtual ~BlimpBase();

private:
    virtual void lift()const = 0;
};

class Blimp: protected BlimpBase{
    void lift()const;
};

class BlimpCarrier{
public:
    add_blimp(BlimpBase& blimp);

private:
    std::vector<BlimpBase* blimp> blimps;
};

As you can see, I have a set of polymorphic blimp classes and I am trying to store then as "references" in the vector by using pointers (I realize you can't store references in vectors, I just don't know how else to describe them). The problem is that most of these objects are allocated on the stack as class members, but I want to add them to this vector so that I can directly modify them (copies won't do). The problem with keeping pointers to these objects is that if these objects go out of scope before the BlimpCarrier does (since they are on the stack), I will have a dangling pointer. I looked into std::unique_ptr and std::shared_ptr, but I don't think I can use them here...

dyp
  • 38,334
  • 13
  • 112
  • 177
Shokwav
  • 654
  • 8
  • 19
  • Just don't allocate them on the stack. – Crowman Jan 23 '14 at 02:10
  • @PaulGriffiths: They are members of classes and I want to "reference" them through this array. I don't think putting them on the heap would help me out any – Shokwav Jan 23 '14 at 02:13
  • It would help you if you put them into the classes as a shared_ptr and reference them in your vector through a shared_ptr or a weak_ptr. – Timo Geusch Jan 23 '14 at 02:15
  • @TimoGeusch: Is that the only way? I have a lot of classes with member classes, and I think wrapping all of the ones I want to "reference" would be very expensive... – Shokwav Jan 23 '14 at 02:17
  • @Shokwav, you have an object lifetime control issue, which either requires extremely careful managing of objects (and will most likely go wrong in the future even if you get it right now) or you'll have to make use of appropriate design patterns. – Timo Geusch Jan 23 '14 at 02:34
  • The `boost::signals` library solves this by returning a handle object from the registration function that removes the pointer once the handle is destroyed. E.g. `BlimpHandle add_blimp(BlimpBase& blimp);` and `BlimpHandle` calls `remove_blimp` in its dtor. You can also make this intrusive, i.e. call `remove_blimp` from `BlimpBases`s dtor. – dyp Feb 03 '14 at 20:37

1 Answers1

0

Assuming you CAN change where they are allocated on the stack, or the classes that have them as members, then you can try this with std::weak_ptr:

class BlimpCarrier{
public:
    add_blimp(std::shared_ptr<BlimpBase>& blimp_ptr)
    {
        blimps.push_back(blimp_ptr);
    }

private:
    std::vector<std::weak_ptr<BlimpBase>> blimps;
};

BlimpCarrier globalCarrier;

void foo()
{
    std::shared_ptr<BlimpBase> instance(new BlimpSubClass());
    globalCarrier.add_blimp(instance);
}

You need an extra step, that when you traverse the vector that you check that the weak_ptr objects have been "Expired" or not, and then remove them yourself from the vector. I'd actually suggest using a std::list instead for a linked list implementation for this type of thing. See cppreference.com for a good example for how to correctly and safely use weak_ptr.

Kevin Anderson
  • 6,850
  • 4
  • 32
  • 54