I came across a weird situation today while coding and I’m hoping someone could shed some light onto why this is happening.
I have a list of pointers to some base class:
std::list<BaseClass*> m_list;
Then I get one of the BaseClass pointers from this list
BaseClass* pBase = m_list.front();
Then I turn this base class into one of its child classes. (This is where I think the weirdness comes into play)
pBase = new ChildClass(*pBase);
The ChildClass uses the BaseClasses copy constructor to copy over all of BaseClasses fields.
Now with this ChildClass I call one of BaseClasses methods to set a field in BaseClass.
pBase->SetSomeIntMember(10);
Now if I check this int value it is 10 as expected, but it appears to only be changing it locally because if I get this same ChildClass from the list again and check it’s int member it will be unchanged.
Hopefully this wasn’t too tricky to follow. What makes this happen? In any situation where there is no polymorphism involved it would obviously not only be a local change as we have a pointer to the class instance. I’m guessing that I’m stomping on the pointer when I create a new ChildClass, but it definitely makes the BaseClass from the list become a ChildClass because the virtual methods still work.
You copy the value of the pointer, not a reference to the pointer.
That is,
is not the same as
Remember, if you want to update the original value, you need to use references or pointers.
Note
The second example contains a memory leak since the original value of
pBaseis discarded beforedelete. To avoid such surprises, use smart pointers, e.g.std::shared_ptr<T>(C++11) orboost::shared_ptr<T>in place ofT*.Do not use
std::auto_ptr<T>because its semantics are not compatible with STL containers.So your list class should be
std::list<std::shared_ptr<BaseClass>>. Another advantage here is that you can use instances of the smart pointer instead of references without messing up the internal reference count.