Удаление данных, на которые указывают несколько списков?

У меня есть объект, который потенциально может оказаться в нескольких списках.

Например

std::list<object*> lista = new std::list<object*>();
std::list<object*> listb = new std::list<object*>();

object* obj = new object();
lista->push_front(obj);
listb->push_front(obj);

Потенциально, есть много объектов, которые попадут в оба списка одинаково. Я понимаю, что умные указатели было бы легко сделать, но назовите меня мазохистом — я бы предпочел выяснить, как это сделать без.

В настоящее время я пробую эту технику:

td::list<object*>::iterator iter;
for(iter = lista->begin(); iter != lista->end(); iter++) {
delete (*iter);
*iter = 0;
}

std::list<object*>::iterator iterB;
for(iterB = listb->begin(); iterB != listb->end(); iterB++) {
if(*iterB != 0) {
delete (*iterB);
*iter = 0;
}
}

delete lista;
delete listb;

Но это нарушает мой эквивалент delete lista; во время выполнения. Надеюсь, кто-то умнее насчет указателей может мне помочь. Заранее спасибо!

Постскриптум Я использую Windows 7 / MinGW.

4

Решение

Основная проблема заключается в том, что вы (по-видимому, вы не предлагаете полный код) delete объект дважды: один раз при итерации по списку A и один раз при итерации по списку B.

Есть три основных решения:

  • Используйте умный указатель для подсчета ссылок, например std::shared_ptr,
    Рекомендуемые. Ваше заявление о том, что вы не хотите использовать умный указатель, похоже, сделано из-за невежества, а не из-за какого-то глупого менеджера.

  • Сохраните узлы также в первичном списке:
    delete узел, только когда вы знаете, что единственный список, в котором он все еще находится, является основным списком.

  • Реализуйте подсчет ссылок самостоятельно:
    Самое простое — снова использовать существующее библиотечное решение, такое как boost::intrusive_ptr, но все, что вам нужно сделать, это тщательно поддерживать счетчик ссылок в каждом узле. delete когда счетчик ссылок уменьшается до 0.

Четвертая возможность — использовать сборщик мусора, такой как сборщик Boehm, но тогда для его поддержки необходимо структурировать код. Или, по крайней мере, это мое впечатление. И может быть трудно получить помощь в этом, так как очень немногие программисты на C ++ используют этот подход (что указывает на то, что он не совсем свободен от проблем).

3

Другие решения

использование shared_ptr или иметь основной список с unique_ptr,

В противном случае имейте основной список, которому принадлежат указатели, и удаляйте из него после очистки, но не удаляйте все остальные списки.

В противном случае, не удаляйте напрямую из списка напрямую. Вместо insert указатели, которые вы хотите, вошли в std::setи либо удалите их из других списков перед удалением (выполните итерацию и найдите в наборе), либо накопите все указатели, которыми вы хотите избавиться, затем массово удалите их из набора.

Это в грубом порядке suckitude по абзацу.

1

Не уверен, почему вы не хотите использовать shared_ptr. Хорошо, оденься. Как насчет того, чтобы просто создать локальный shared_ptr? Если нет, тогда загрузите оба списка в один основной список. Очистите два подсписка и удалите каждый элемент в основном списке, а также очистите основной список.

0

В соответствии

if(*iterB != 0) {

* iterB никогда не будет 0. Так что вы дважды удаляете.

0

Добавить счетчик поля к вашему object, По умолчанию инициализировать до 0. Добавить +1 при добавлении в список. -1 при удалении из списка. Если counter==0удалите object,

Это не потокобезопасно, так как shared_ptr, но это может быть намного быстрее по той же причине.

0
По вопросам рекламы [email protected]