валидность итератора, после вызова erase () в std :: set - PullRequest
10 голосов
/ 28 октября 2009

Удалить вызов в std :: set, сделать недействительным итератор? Как я сделал ниже 5-й от последней строки ..? если да, то какой лучший способ стереть все элементы из набора

class classA
{
public:
    classA(){};
    ~classA(){};
};
struct structB
{
};

typedef std::set <classA*, structB> SETTYPE;        
typedef std::map <int, SETTYPE>MAPTYPE;

int __cdecl wmain (int argc, wchar_t* pArgs[])
{
    MAPTYPE mapObj; 
    /*
      ...
      ..   Some Operation Here
      ...
      */
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {       
        SETTYPE li=(*itr1).second;
        for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
        {
            classA *lt=(classA*)(*itr2);
            li.erase(itr2); 
            delete lt; // Does it invalidate Iterator ?
        }
    }
}

Ответы [ 3 ]

41 голосов
/ 28 октября 2009

из стандарта 23.1.2

Элементы вставки не должны влиять на действительность итераторов и ссылок на контейнер, а члены стирания должны делать недействительными только итераторы и ссылки на стертые элементы.

EDIT

В вашем случае itr2 становится недействительным после стирания, поэтому его приращение вызывает неопределенное поведение. В этом случае вы можете следовать совету reko_t, в общем, вы можете попробовать это:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}

, который будет увеличивать итератор до , удаляя его предыдущее значение из набора.
КСТАТИ. itr2 не отменяется delete lt;, но li.erase(itr2);

7 голосов
/ 28 октября 2009

Удаление в порядке.

Проблема в том, что вы удаляете - и, таким образом, делаете недействительным - itr2, но используете его для итерации цикла.

i.a.w. после первого стирания ++itr2 имеет неопределенные результаты.

Шаблон, который я использую в этой ситуации, таков:

while(itr2 != end())
{
   iterator toDelete = itr2;
   ++itr2;   // increment before erasing!
   container.erase(toDelete);
}

В некоторых нестандартных имплантах STL стирание возвращает следующий итератор, поэтому вы можете сделать:

while(itr2 != end())
   itr2 = container.erase();

это не переносимо.


set<A*,B> странно, хотя - в стандартном значении B будет компаратором.

2 голосов
/ 28 октября 2009

Поскольку вы, очевидно, просто удаляете каждый элемент набора, вы можете просто сделать:

    for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    {
            classA *lt=(classA*)(*itr2);
            delete lt;
    }
    li.clear(); // clear the elements
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...