You break the rule of three / five.
You will undoubtedly need to overload the assignment and create a copy (at least) for your class to work as it wishes. The default copy constructor will simply copy the iterator so that you get a second object containing a copy of the original iterator, pointing to the original object, so when the copy is destroyed, this element will be removed from your collection.
Obviously, you want to add a new object to your collection and have this object while holding the iterator for the new object in the collection when the copy is being built.
Similarly, the default assignment operator will copy the iterator from source to target. You probably just want to leave the iterator unchanged (i.e. still refer to the same object in the collection, since assignment results in the same object having a different value).
#include <list> #include <iostream> class Box { private: std::list <Box*>::iterator iter; public: static std::list <Box*> List; Box() { List.push_front(this); iter = List.begin(); std::cout << "Constructing box." << std::endl; } ~Box() { std::cout << "Trashing box." << std::endl; List.erase(iter); } void lookInside() { std::cout << "It empty." << std::endl; }; // JVC: added next two overloads: Box &operator=(Box const &src) { // don't assign anything. return *this; } Box(Box const &other) { List.push_front(this); iter = List.begin(); std::cout << "Copy constructing box.\n"; } }; std::list <Box*> Box::List; int main() { Box Box_1; Box Box_2; Box Box_3; Box_1 = Box_2; // No longer causes problem! for (auto iter : Box::List) { iter->lookInside(); } std::cout << "The list contains " << Box::List.size() << " boxes." << std::endl; return 0; }
Aside: this whole project is probably a mistake. The code above covers errors at a relatively microscopic level, but does nothing to fix the underlying design problem.
source share