Чем итератор отличается от указателя при освобождении памяти в C ++ - PullRequest
1 голос
/ 09 февраля 2020

У меня есть класс "DMRecSessionObj", чьи объекты динамически распределяются с использованием новых и сохраняются в карте.

static std::map<string,DMRecSessionObj*> mapExpSessData;
DMRecSessionObj* dmRecSessObj = new DMRecSessionObj(atoi(p_callNum),atoi(p_totCalls), sessionKey);
mapExpSessData.insert(std::pair<string,DMRecSessionObj*>(sessionKey,dmRecSessObj));

Во время освобождения памяти я использую очевидный ниже метод

delete dmRecSessObj;
dmRecSessObj = NULL; //to prevent it from being a dangling pointer

Но я немного растерялся, пытаясь освободить память с помощью итератора, как показано ниже:

std::map<std::string,DMRecSessionObj*>::iterator itr_del = mapExpSessData.find(tmp_sessionId);
if (itr_del != mapExpSessData.end()){
   mapExpSessData.erase(tmp_sessionId);
   delete itr_del->second;
}

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

Спасибо.

1 Ответ

1 голос
/ 09 февраля 2020

После вызова mapExpSessData.erase(tmp_sessionId); узел на карте, на который указывает itr_del, был удален. В этом случае вызов delete itr_del->second; является неопределенным поведением, поскольку вы пытаетесь получить доступ к освобожденной памяти.

Сначала необходимо удалить значение на карте, а затем удалить узел на карте:

delete itr_del->second;
mapExpSessData.erase(itr_del);

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

...