Удаление «значения» из мультикарты - PullRequest
1 голос
/ 05 декабря 2011

Мое требование - удалить «значение» из мультикарты, а не «ключ». Ключ может иметь несколько значений, и i хочет удалить конкретное значение. Моё требование аналогично удалению узла из связанного списка.

Я делаю это, используя multimap::erase() метод. Но после удаления, если я пытаюсь напечатать значения мультикарты, значения, удаленные с помощью multimap::erase(), также будут напечатаны.

ниже мой фрагмент кода:

void Clientqueues::clearSubscription(string name,string sessionid)
{
    pair<multimap<string,string>::iterator,multimap<string,string>::iterator> i;
    multimap<string, string>::iterator j;
    i = registeredClientInfo.equal_range(name);

    if (j == registeredClientInfo.end())
            return;
    for(j=i.first;j != i.second;++j)
    {
        if((j->second) == sessionid) registeredClientInfo.erase(j->second);
    }

    for(j=i.first;j != i.second;++j)
    {
        cout<<""<<j->second<<endl;///This prints the erased values too;
    }

}

Я что-то не так делаю? Любая помощь в этом отношении с благодарностью.

Ответы [ 2 ]

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

Самое главное, вы звоните erase(j->second), когда вы хотели позвонить erase(j).Вы не стираете элемент мультикарты, на которую указывает j, вы стираете все элементы, ключи которых равны значению элемента, на который указывает j (то есть sessionid).Я ожидаю, что это ничего.

Также: снова вызовите equal_range после завершения цикла erase - эффект от использования стертого итератора не определен, поэтому, если вы стерли первый итератор i.first, то выне могу начать итерацию оттуда потом.

Обратите внимание, что это также означает, что в вашем цикле есть ошибка, которая выполняет erase, поскольку в случае, если вы вызываете erase, вы увеличиваете j когда он содержит значение итератора, которое больше не действует.К сожалению, правильный код:

for(j=i.first;j != i.second;)
{
    if((j->second) == sessionid) {
        auto next = j;
        ++next;
        registeredClientInfo.erase(j);
        j = next;
    } else {
        ++j;
    }
}

Или, если вы предпочитаете:

for(j=i.first;j != i.second;)
{
    auto current = j;
    ++j;
    if((current->second) == sessionid) registeredClientInfo.erase(current);
}

Или если запись уникальна для пары ключ / значение, так что вам нужно только удалитьсамое большее, то одно:

for(j=i.first;j != i.second;++j)
{
    if((j->second) == sessionid) {
        registeredClientInfo.erase(j);
        break;
    }
}

if (j == registeredClientInfo.end()) return; тоже не правильно, поскольку j неинициализируется, когда вы это делаете.Если ключ не найден, то equal_range возвращает пустой диапазон (два равных значения итератора), поэтому остальные ваши циклы все равно ничего не сделают.

0 голосов
/ 05 декабря 2011

Если вы удалили i.first или i.second, итераторы становятся недействительными, что подразумевает неопределенное поведение.

...