LINUX.ORG.RU

Очистка std::list с удалением объектов


0

1

Есть такой код:

#include <list>
#include <stdio.h>

using namespace std;

class MyClass
{
	public:
		MyClass(int id);
		~MyClass();

	private:
		int m_id;
};

int main(int argc, char * argv[])
{
	list<MyClass*> m_list;

	int i;
	for (i = 1; i <= 4; ++i)
	{
		MyClass * m_myClass = new MyClass(i);
		m_list.push_back(m_myClass);
	}

	m_list.clear();

	return 0;
}

MyClass::MyClass(int id)
	: m_id(id)
{
	printf("MyClass::MyClass(%d)\n", id);
}

MyClass::~MyClass()
{
	printf("MyClass::~MyClass(%d)\n", m_id);
}

Суть в том, что я циклически создаю объекты и помещаю их в list. Но как мне потом средствами самого list удалить все объекты из памяти? Или прийдётся ето делать вручную?

Вывод программы такой:

MyClass::MyClass(1)
MyClass::MyClass(2)
MyClass::MyClass(3)
MyClass::MyClass(4)

деструкторы класса не срабатывают. Может, я не правильно понимаю документацию, но здесь http://www.cplusplus.com/reference/list/list/clear/ написано:

All the elements in the list container are dropped: their destructors are called, and then they are removed from the list container, leaving it with a size of 0.

почему тогда в моём случае деструкторы не вызываются?

.Ты в списке хранишь указатели на обьекты, а не сами обьекты. «деструктор» указателя ничего не делает. Удаляй вручную или используй умные указатели.

placement_new ★★
()

почему тогда в моём случае деструкторы не вызываются?

Потому что хранишь указатели, а не сами объекты. Либо смарт поинтеры юзай, либо руками удаляй.

oh-la-la
()

Вариант со смарт указателями. Компилировать с флагом -std=c++0x или -std=c++11.

#include <list>
#include <memory>
#include <iostream>

using namespace std;

class MyClass
{
public:
    MyClass(int id)
        : m_id(id)
    {
        cout << "MyClass::MyClass(" << m_id << ")\n";
    }

    ~MyClass()
    {
        cout << "MyClass::~MyClass(" << m_id << ")\n";
    }

private:
    int m_id;
};

int main()
{
    list<unique_ptr<MyClass>> lst;

    for (int i = 0; i != 4; ++i)
        lst.emplace_back(new MyClass(i));
}

Вывод:

MyClass::MyClass(0)
MyClass::MyClass(1)
MyClass::MyClass(2)
MyClass::MyClass(3)
MyClass::~MyClass(0)
MyClass::~MyClass(1)
MyClass::~MyClass(2)
MyClass::~MyClass(3)

А, в общем-то, в списке лучше хранить объекты по значению, а не указатели. Т.е. вместо list<unique_ptr<MyClass>> или list<MyClass*> использовать просто list<MyClass>.

alexeiz
()
Ответ на: комментарий от alexeiz

в списке лучше хранить объекты по значению, а не указатели

очень плохой совет, если он звучит без дополнительных оговорок

anonymous
()
Ответ на: комментарий от xterro

Нужно быть готовым к тому, что при копировании листа будут тупо копироваться все объекты. Это, конечно, не вектор, но все равно может привести к неприятным эффектам. Не могу представить случая, когда действительно лучше хранить в контейнере сам объект, а не smart pointer на него. Разве что POD. Это и есть список оговорок, каковым надо снабжать оспариваемое мной утверждение.

anonymous
()
Ответ на: комментарий от anonymous

Нужно быть готовым к тому, что при копировании листа будут тупо копироваться все объекты.

да если по ссылке низя

Не могу представить случая, когда действительно лучше хранить в контейнере сам объект, а не smart pointer на него

когда не можешь просто этого сделать

class A
{
   protected:
      void* operator new(size_t) { }
      void  operator delete(void*) { }
      // new[] и delete[]
};
Boy_from_Jungle ★★★★
()
Ответ на: комментарий от anonymous

А хранить простой указатель на объект в писках и векторах не возбраняется? Ну, естественно при условии, что в деструкторе объекта буду пробегать по этому списка и для каждого вызывать delete?

xterro ★★★★★
()
Ответ на: комментарий от alexeiz

А, в общем-то, в списке лучше хранить объекты по значению, а не указатели.

А если у меня в классе будет щё один list или string, он мне не вылетит в segfault в один прекрасный момент?

abr_linux
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.