Лучший способ справиться с подобными вещами - использовать стандартный контейнер вместо какой-то домашней работы, если у вас нет веских причин и вы не знаете, что делаете и почему ...
станд :: вектор <>
станд :: Список <>
Но чтобы выбрать контейнер, важно знать, что вы делаете, какова продолжительность жизни.
@ Джек - независимо от того, что вы делаете, стандартные контейнеры волшебным образом не заботятся о выделенных вручную объектах для вас. Это принципиально невозможно.
Вы должны изменить свой подход к проблеме, чтобы воспринимать проблему как «объекты, выделенные вручную». Как только вы совершите этот скачок и поймете, что это плохой путь, вы можете выбирать между «они объектами значения» или «ими будет управлять shared_ptr».
EX1: использование shared_ptr для хранения новых объектов (этот подход следует использовать, если копирование вокруг MyNode - плохая идея [производительность, собственные ресурсы, сохраненное состояние]):
void MyFunction()
{
typedef boost::shared_ptr<MyNode> NodePtr;
std::list<NodePtr> my_list;
my_list.push_back(NodePtr(new MyNode(args...)));
my_list.push_back(NodePtr(new MyNode(args...)));
...
// when this function exits, the nodes, which are owned by shared_ptr's
// which are themselves owned by a stack instance of std::list<>
// will be automatically deleted, no leaks anywhere...
}
EX2: это то, что вы делаете, если ваши узлы дешевы, могут рассматриваться как копируемые объекты (семантика значений):
void MyFunction()
{
std::vector<MyNode> my_list;
my_list.push_back(MyNode(args...));
my_list.push_back(MyNode(args...));
...
// when this function exits, the nodes, which are shored directly as copies
// in the vector container, will be automatically deleted, no leaks anywhere...
}
И если вы действительно по какой-то причине предпочитаете управлять экземплярами вручную (обычно вы делаете это, потому что время жизни на самом деле не привязано к времени жизни отдельного контейнера, а имеет некоторый нерегулярный жизненный цикл, который не может быть аккуратно инкапсулирован ничем, кроме собственного алгоритма ):
void MyFunction()
{
std::list<MyNode*> my_list;
my_list.push_back(new MyNode(args...));
my_list.push_back(new MyNode(args...));
...
// we must manually deallocate the nodes because nothing else has been given
// responsibility anywhere (we're manually managing them)
typedef std::list<MyNode*>::iterator iterator;
for (iterator it = std::begin(my_list), end = std::end(my_list); it != end; ++it)
delete *it; // manually releases our allocated memory from the heap
// the "head" is still deleted automatically because it is stack allocated
// (the list object)
}