Разыменование итератора списка C ++ STL - PullRequest
0 голосов
/ 27 апреля 2011

Я перебираю два списка STL (L1, L2) примерно так:

list<int>::const_iterator itr1 = L1.begin();
list<int>::const_iterator itr2 = L2.begin();

for (itr1; itr1 != L1.end(); itr1++) {
   if (*itr1 < *itr2) {
     //some code
   }

}

Он хорошо компилируется, но когда я его запускаю, он говорит: "Выражение: итератор списка не может быть разыменован"

Теперь в классе мы сделали фиктивную версию списка STL, где мы написали наш собственный список STL и перегрузили оператор * для разыменования итератора. Однако, очевидно, это не работает здесь.

Как я могу разыменовать итератор, или если список STL делает это по-другому, как он это делает. Я просмотрел это:

http://www.sgi.com/tech/stl/List.html

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

Кто-нибудь знает, что здесь происходит? Спасибо

Вот пастбина:

http://pastebin.com/YRddqjmN

Ответы [ 5 ]

3 голосов
/ 27 апреля 2011

Это (специфичное для реализации) сообщение подсказывает мне, что вы разыменовали недействительный итератор. Это не имеет ничего общего с семантикой синтаксиса / времени компиляции, поэтому неудивительно, что ваш компилятор не жаловался. Однако обратите внимание, что итераторы имеют семантику времени выполнения: в этом случае я бы поспорил, что код вызывается с пустым списком L2, так что itr2 == L2.end(). Это означает, что *itr2 приводит к неопределенному поведению. К счастью, это похоже на сообщение об ошибке, а не на ваше лицо.

3 голосов
/ 27 апреля 2011

Мое предположение:

L2 пусто, поэтому L2.begin() совпадает с L2.end().

Это означает, что L2.begin() возвращает не ссылочный итератор, и, таким образом, вы вызываете неопределенное поведение.

2 голосов
/ 27 апреля 2011
while ( *itr2 < *itr1 ) {
    itr2++;
}

В этом коде нет проверки на выход из конца L2. Возможно, добавьте чек на itr2 != L2.end() к этому.

0 голосов
/ 27 апреля 2011

Другие ответы верны: разыскивается неверный итератор списка из-за двух ошибок.Глядя на ваш pastebin,

Это условие обратное:

if ( (*itr1 == *itr2) && (itr2 != L2.end()) ) {

Это должно быть

if ( (itr2 != L2.end()) && (*itr1 == *itr2) ) {

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

if ( L1.empty() && L2.empty() ) {
            cout << "Returning an empty list because the two arugment lists were empty\n\n";

должно быть дизъюнкцией:

if ( L1.empty() || L2.empty() ) {
            cout << "Returning an empty list because at least one of the two argument lists was empty\n\n";

, но в этом даже нет необходимости.

(О, и знаете ли вы о set_intersection , который является частью стандартной библиотеки?)

0 голосов
/ 27 апреля 2011

Стандартный итератор списка может быть разыменован, если он находится в пределах диапазона вашего списка, то есть [list.begin (), list.end ()), пока ваш список не пуст.

...