2015-01-23 3 views
-2

Каков правильный способ удаления содержимого списка. В настоящее время я это делаю.Удаление списков в C++ вызывает сбой

std::list<CSchSuggestBar*>::const_iterator iter = m_pRescheduleReasons.begin(); 
for (; iter != m_pRescheduleReasons.end(); ++iter) 
{ 
    delete *iter; 
} 

однако удаление * iter, похоже, вызывает сбой.

Это предпочтительнее, если я просто позвонить m_pRescheduleReasons.clear()

редактировать:

Путь Как указатели хранятся в списке, как выглядит следующим образом: (я сделал отдельный проект, чтобы изолировать проблему: когда удаляемый называется в первый раз появляется авария .. однако есть действительный объект, в котором указатель указывает слишком Так им не слишком уверен, почему он врежется

std::vector<Foo*> f; 
for(int i = 0; i < 10; i++) 
{ 
    f.push_back(f1); 
} 
std::vector<Foo*>::const_iterator it = f.begin(); 
for (; it != f.end(); ++it) 
{ 
    delete *it; 
} 

EDIT:? я решил это была глупая ошибка от моего имени

+0

Что на самом деле указывают указатели в списке? Как добавить элементы в список? * Что * вы добавляете в список? –

+0

Вы ищете его? –

+1

Я нашел так много хороших предложений от googling «delete list in C++» –

ответ

2

Использование

std::list<std::unique_ptr<SomeType>> mylist; 

, когда он будет автоматически удалять его содержимое list::clear() или list::~list(). Поскольку unique_ptr не могут быть скопированы, вы должны переместить их

mylist.push_back(std::move(std::unique_ptr<SomeType>(new SomeType(args)))); 
mylist.push_back(std::move(make_unique(new SomeType(args))); // C++14 

Вы также можете использовать list::emplace как в

mylist.emplace_back(new SomeType(args)); 

, но если распределение узел выходит из строя, память, выделенную new SomeType(args) не будет назначен unique_ptr и, следовательно, утечки.

+0

+1 за предложение 'unique_ptr'. -1 для предложения 'emplace_back' для контейнера, содержащего' unique_ptr'. Если распределение узла списка не удастся, указатель, скорее всего, будет течь. –

+0

'std :: unique_ptr' - правильный выбор в * большинстве случаев *. Но я думаю, что это не касается реальной проблемы. Если искатель применит это предложение, проблема, вероятно, будет еще больше. Это соображение проголосовало. – Wolf

+0

@SebastianRedl Хорошая точка. Я отредактировал свой ответ. – Walter

0

Старая вещь, я думаю, вы хотите что-то вроде deleteAll macro в Qt.

bool deleteCSchSuggestBar(CSchSuggestBar *item) 
    { 
     delete item; 
     return true; 
    } 

    m_pRescheduleReasons.remove_if(deleteCSchSuggestBar); 
    m_pRescheduleReasons.clear(); 
+0

вы можете использовать лямбда в 'remove_if'. – Walter

+0

, конечно, но я обычно нацелен на старые версии C++, а не на C++ 11. – Maquefel

+0

Почему вы ограничиваете старый C++? Сколько лет? 1998? предварительно стандарт? – Walter

0

код вы вывесили

std::list<CSchSuggestBar*>::const_iterator iter = m_pRescheduleReasons.begin(); 
for (; iter != m_pRescheduleReasons.end(); ++iter) 
{ 
    delete *iter; 
} 

работает отлично. Я сделал из него working example.

Авария может быть вызвана самим вызовом деструктора.

Или, что более вероятно, в вашем случае: вы звоните delete на оборванных указатель (адрес бывшего объекта, который был уже разрушен). Попытайтесь добавить эту строку после уничтожения всех объектов в цикле:

m_pRescheduleReasons.clear(); 

В результате получается пустой список.

+0

Я обновил свой ответ. – CodersSC

-1

Это предпочтительнее, если я просто называю m_pRescheduleReasons.clear()

Это действительно сводится к прецеденту ...

если вы используете удаления ITER; вызов, только итераторы будут признаны недействительными .... Но если вы хотите удалить указатель тоже, тогда, delete * iter должен это сделать.

Рассмотрим это:

Если у вас есть объекты в этом списке, то удаление этих объектов будет действителен случай использования.

Но скажите в сценарии использования, таком как шаблон субъекта-наблюдателя, где вам нужно поддерживать список наблюдателей, случайное удаление наблюдателей на самом деле не было бы хорошим выбором дизайна.

+0

Ответчик заявил, что 'delete * iter, похоже, вызывает сбой. Я думаю, что это действительно так, но сам« вредоносный »деструктор не включен в сообщение. BTW: ассер не использует 'delete iter', я думаю, что этот ответ пока не помогает (-1) – Wolf

+0

Этот ответ был на вопрос Предпочтительно ли я просто вызвать m_pRescheduleReasons.clear() ?? Я не понимаю, как это заслуживает голосования вниз .... Вариант использования является законным, не так ли? – basav