Это правильный способ удалить и стереть указатели на объекты, хранящиеся в векторе? - PullRequest
5 голосов
/ 07 декабря 2011

Я не очень хорошо разбираюсь в STL, и я видел несколько постов, похожих на мои требования, и запутался. Итак, мне нужно предложение по следующему коду.

        SomeStruct someStruct(identifier);
        std::vector<SomeStruct*>::iterator it = std::find_if(vWrapper.begin(), vWrapper.end(), SomeStruct::Find_SomeStruct(&someStruct));
        if(it != vWrapper.end()) 
        {
            ...
            delete *it;  
            it = vWrapper.erase(it);
        }

Я пытаюсь заглянуть в вектор на основе идентификатора, а затем удалить указатель на объект, сохраненный в векторе.

Я видел сообщение . Он использует цикл for и переназначает итераторы. Кроме того, ни один пост не использовал find_if (), затем удаляю и стираю.

Правильно ли я это делаю?

Ответы [ 3 ]

6 голосов
/ 07 декабря 2011

Формально то, что вы делаете, это неопределенное поведение, но практически говоря, это нормально. Неопределенное поведение происходит потому, что std::vector требует, чтобы все его содержимое было копируемым и присваиваемый, всегда, и delete делает значение указателя это было принят недействительным и, следовательно, не подлежит копированию. На практике: std::vector не собираюсь скопировать значение указателя, если вы удалите его сразу после, и я сегодня не знаю машины, где удаленное значение указателя не может копировать без риска. (Только не разыменовывайте это.) Если вы действительно Чтобы избежать неопределенного поведения, вы можете сделать что-то вроде:

SomeStruct* tmp = *it;
it = vWrapper.erase(it);
delete tmp;

но, честно говоря, я не уверен, что оно того стоит.

3 голосов
/ 07 декабря 2011

Это вызывает неопределенное поведение. Для объяснения прочитайте ответ @James Kanze .

Я бы предпочел перейти к следующему вопросу: если в другой теме ни один из ответов не использовал std::find_if, то это потому, что в этих сообщениях не говорится об удалении и удалении конкретного элемента. Oни похоже, что все элементы удалены, или лишь немногие из них использовали функтор, где проверяют, какие объекты удаляются, что тоже хорошо.

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

Ну, это то, что я мог бы сказать для правильно написанного std::find_if.

Однако на самом деле я не мог понять ваш код, особенно эти две строки:

//I formatted the code so that entire code is visible without 
//scrolling horizontally

SomeStruct someStruct(identifier); 
std::vector<SomeStruct*>::iterator it = std::find_if
                                   (
                                     vWrapper.begin(), 
                                     vWrapper.end(),
                                     SomeStruct::Find_SomeStruct(&identifier)
                                   );

Что там делает первая строка? Вы объявили переменную и забыли ее? Ну, может быть, вы используете это где-то еще; в этом случае все в порядке.

Но что такое SomeStruct::Find_SomeStruct? Это вложенный класс, который может действовать как функтор? статическая функция или что? Ваша компиляция успешно? Полный ответ также зависит от этих вопросов, которые я поставил.

1 голос
/ 07 декабря 2011

Лично у меня нет сырых указателей в контейнере, чтобы не иметь дело с проблемами, которые вы задаете.Я не думаю, что выбрать правильный способ их удаления.Вместо этого используйте умный указатель, такой как std :: shared_ptr, и он удалит свой необработанный указатель, которым владеет, когда умный указатель выйдет из области действия RAII .

Поэтому вместо

std::vector<SomeStruct*> vec;

используйте

std::vector<std::shared_ptr<SomeStruct>> vec;

Так как насчет удаления элемента?

vec.erase(std::remove_if( vec.begin(), vec.end(), 
  [&vec]( std::shared_ptr<SomeStruct> & item ) 
  {
    bool condition = // The condition on which the item will de deleted. e.g. item->x == 0;
    return condition;
  }
),vec.end());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...