Здравствуйте, yaser, Вы писали:
Y>есть что-то типа такого Y>typedef std::list<class_impl*> MainList; Y>typedef std::list<MainList::iterator> SubMainCList;
Y>MainList c; Y>SubMainCList cs;
Y>где-то в коде Y>cnl::MainList::iterator i = c.insert(channel->consumers.begin(), impl); Y>cs.push_back(i);
Y>еще где-то в коде Y>for(SubMainCList::iterator it = cs.begin(); it != cs.end(); it++){ Y> if (*(*it) == this) { Y> с.erase(*it); Y> cs.erase(it); Y> }
Y>Корректно ли хранить итератор? Правильно ли в такой последовательности удалять?
Согласно стандарту лперация вставки элемента в список не влияет на корректность ссылок и итераторов. То есть при выполнении вами операции
cnl::MainList::iterator i = c.insert(channel->consumers.begin(), impl);
все другие итераторы в списке остаются корректными.
Операция удаления из списка также не влияет на другие итераторы за исключением итератора, удаляемого элемента. Поэтому ваш цикл
for(SubMainCList::iterator it = cs.begin(); it != cs.end(); it++){
if (*(*it) == this) {
с.erase(*it);
cs.erase(it);
}
будет некорректным, так как вы вполняете оператор it++ для уже ставшего некорректным итератора после удаления элемента в строке с функцией cs.erase(it);. Об этом вы можете почитать по ссылке http://clipper.borda.ru/?1-6-0-00000006-000-0-0-1319646235
Здравствуйте, yaser, Вы писали:
Y>есть что-то типа такого
приводите конкретный код, а не "что-то типа"
выкладывайте на ideone.com, codepad.org
Y>Корректно ли хранить итератор?
хранить можно, но не забывайте, что иногда они могут инвалидироваться
конкретно в вашем случае они не инвалидируются при вставках новых элементов в список
если вы удаляете элемент или очищаете список, то ранее сохраненный итератор на элемент инвалидируется: его нельзя разыменовывать, инкрементить или передавать в функции типа erase, insert, etc
>>Правильно ли в такой последовательности удалять?
неправильно, потому что после cs.erase(it) итератор it инвалидируется и ему нельзя делать ++
аналогичный треп можно найти здесь: http://rsdn.ru/forum/cpp.applied/4547482.flat.aspx
Здравствуйте, Сыроежка, Вы писали:
С>Здравствуйте, yaser, Вы писали:
Y>>есть что-то типа такого Y>>typedef std::list<class_impl*> MainList; Y>>typedef std::list<MainList::iterator> SubMainCList;
Y>>MainList c; Y>>SubMainCList cs;
Y>>где-то в коде Y>>cnl::MainList::iterator i = c.insert(channel->consumers.begin(), impl); Y>>cs.push_back(i);
Y>>еще где-то в коде Y>>for(SubMainCList::iterator it = cs.begin(); it != cs.end(); it++){ Y>> if (*(*it) == this) { Y>> с.erase(*it); Y>> cs.erase(it); Y>> }
Y>>Корректно ли хранить итератор? Правильно ли в такой последовательности удалять?
Обратите внимание также на то, что в вашем примере кода, итераторы в списке располагаются в обратном порядке по сравнению с элементами исходного списка. Так как сами элементы с помощью insert добавляются в начало списка, а итераторы с помощью push_back добавляются в конец списка.
Здравствуйте, Сыроежка, Вы писали:
С>будет некорректным, так как вы вполняете оператор it++ для уже ставшего некорректным итератора после удаления элемента в строке с функцией cs.erase(it);. Об этом вы можете почитать по ссылке http://clipper.borda.ru/?1-6-0-00000006-000-0-0-1319646235
Немного фоотоп: честно говоря, я бы не стал приводить в качестве первоисточника свежеиспеченный форум с десятком сообщений, да ещё давать урл на пост, в котором утверждается, что Герб Саттер — не прав
Поэтому и первый код, предложенный Саттером, и второй код — оба они не корректные!
То есть пример Герба Саттера и его рассуждения вообще не состоятельны! Так как можно долго рассуждать про некорректный код!
Здравствуйте, Mr.Delphist, Вы писали:
MD>Здравствуйте, Сыроежка, Вы писали:
С>>будет некорректным, так как вы вполняете оператор it++ для уже ставшего некорректным итератора после удаления элемента в строке с функцией cs.erase(it);. Об этом вы можете почитать по ссылке http://clipper.borda.ru/?1-6-0-00000006-000-0-0-1319646235
MD>Немного фоотоп: честно говоря, я бы не стал приводить в качестве первоисточника свежеиспеченный форум с десятком сообщений, да ещё давать урл на пост, в котором утверждается, что Герб Саттер — не прав
MD>
MD>Поэтому и первый код, предложенный Саттером, и второй код — оба они не корректные!
MD>
MD>То есть пример Герба Саттера и его рассуждения вообще не состоятельны! Так как можно долго рассуждать про некорректный код!
Так какие пробелмы?! если вы считаете, что эти утверждения неверные, и что приведенный код Гербом Саттером следует использовать на практике (а я считаю, что ни в коем случае его не следует приводить на практике, а использовать именно возвращаемый итератор из функции erase), то напишите там свои возражения!
Здравствуйте, Сыроежка, Вы писали:
С>Здравствуйте, Mr.Delphist, Вы писали:
С>Так какие пробелмы?! если вы считаете, что эти утверждения неверные, и что приведенный код Гербом Саттером следует использовать на практике (а я считаю, что ни в коем случае его не следует приводить на практике, а использовать именно возвращаемый итератор из функции erase), то напишите там свои возражения!
А можно, мы сами решим где и что писать?
Во-первых, утверждение, что код некорректен, только потому, что в некотором частном случае (итератор == l.end()) он не работает, некорректно. Точно также можно и про твой код сказать, что итератор может быть невалидным и вызывать erase нельзя.
Во-вторых, раз уж ты взялся так лихо менять одни контейнеры на другие, надо быть последовательным. Не мог бы ты нам продемонстрировать "правильный вызов erase" для std::map или std::set согласно стандарту 2003 года? Речь идёт про std::list и подсовывание другого контейнера выглядит, по меньшей мере, странно.
Здравствуйте, k.o., Вы писали:
KO>Здравствуйте, Сыроежка, Вы писали:
С>>Здравствуйте, Mr.Delphist, Вы писали:
С>>Так какие пробелмы?! если вы считаете, что эти утверждения неверные, и что приведенный код Гербом Саттером следует использовать на практике (а я считаю, что ни в коем случае его не следует приводить на практике, а использовать именно возвращаемый итератор из функции erase), то напишите там свои возражения!
KO>А можно, мы сами решим где и что писать?
KO>Во-первых, утверждение, что код некорректен, только потому, что в некотором частном случае (итератор == l.end()) он не работает, некорректно. Точно также можно и про твой код сказать, что итератор может быть невалидным и вызывать erase нельзя.
KO>Во-вторых, раз уж ты взялся так лихо менять одни контейнеры на другие, надо быть последовательным. Не мог бы ты нам продемонстрировать "правильный вызов erase" для std::map или std::set согласно стандарту 2003 года? Речь идёт про std::list и подсовывание другого контейнера выглядит, по меньшей мере, странно.
Частный случай — это как раз то, что приводит Герб Саттер! Есть общая идиома применения стандартной операции к последовательным контейнерам, которая заключается в том, что надо писать аткой код, который не повзволит программисту допустить ошибку. Когда вы опираетесь на чатсный случай, то это источник всех ошибок. Такую ошибку очень трудно затем обнаружить. Более того код станвится трудно сопровождаемым. Так как, допутим, было принято решение перейти с одного последовательного контейнера на другой последовательный контейнер. А в вашем проекте может быть нескольок сотен модулей! И вы замучаетесь затем искать все места в коде, где вы исопользовалпи частный, не переносимый метод для работы с последовательными контейнерами. Хотя с самого начала вы могли использовать правильную идиому применения функции erase, и тогда у вас такой проблемы не возникла.
Что касается вопроса, где писать, то проблема возникает в том, что вы начинаете обсуэдать содержание, которые не привдеено в этйо теме. Надо не отрывать обсуждение от первоисточника, в противном случае получается другая тема в теме. Только и всего. Ежели это как-то ущемсляет ваше самолюбие, то это уже ваши личные проблемы.