`std :: forward_list` ходить, пока итератор не станет нулевым?

Можно ли пройти std::forward_list, увеличивая итератор, пока указанный интегратор не станет нулевым? По старинке ...

В следующем примере я создаю функцию print().

#include <iostream>
#include <forward_list>

void print(std::forward_list<int>::iterator fl_it, std::forward_list<int>::iterator e) {

    while (fl_it != e) {
        std::cout << *fl_it  << ' ';
        ++fl_it;
    }

    std::cout << std::endl;  //-> 1 2 3
}

int main() {
    std::forward_list<int> fl = {1, 2, 3};
    print(fl.begin(), fl.end());
    std::cout << std::endl;
    return 0;
}

Обратите внимание, как необходимо передать итератор, указывающий на конец списка, чтобы мы знали, когда остановиться.

Что я хочу сделать, так это просто передать итератор в начало списка и двигаться дальше, пока не останется элементов, например:

void print(std::forward_list<int>::iterator fl_it) {
    while (fl_it != nullptr) {
        std::cout << *fl_it << ' ';
        ++fl_it;
    }
    std::cout << std::endl;
}

Мой компилятор не любит это fl_it != nullptr дело.

Моим первым желанием было найти способ проверить, является ли итератор нулевым и ссылается ли он на конец списка. К сожалению, такого метода не существует.

Любые идеи?


person kmiklas    schedule 12.01.2017    source источник
comment
Подумайте об этом так: если бы у вас был первый элемент массива и никакой другой информации, смогли бы вы добраться до конца?   -  person AndyG    schedule 12.01.2017
comment
И сможете ли вы определить конец, когда дойдете до него?   -  person jaggedSpire    schedule 12.01.2017
comment
Следует отметить, что существуют некоторые виды итераторов, которые в некотором роде имеют эту функциональность --_ 1_ для одного из них есть istream& конструктор и конструктор по умолчанию. Итератор, созданный по умолчанию, действует как конечный итератор для диапазона, и итератор, созданный istream, будет сравниваться с итератором, созданным по умолчанию, когда он встретит конец обернутого istream. Таким образом, вы можете передать istream_iterator в функцию и просто построить внутри нее конечный итератор. Но это не относится ко многим типам итераторов.   -  person jaggedSpire    schedule 12.01.2017
comment
@AndyG, в массиве нет, вам нужно количество аргументов. Связанный список - это совсем другое дело: у нас есть возможность установить указатель последнего узла на контрольное значение.   -  person kmiklas    schedule 12.01.2017


Ответы (3)


Вы этого не сделаете.

std::forward_list - это стандартный библиотечный контейнер. Как и все контейнеры, он меняется с begin на end. Нет никаких «нулевых» итераторов. Следовательно, операции выполняются с рядом итераторов.

Обратите внимание, что предложение Range TS намеревается разрешить "дозорные" типы вместо того, чтобы требовать конечных итераторов. Единственный дозорный может быть равен конечному итератору любого диапазона. Так что forward_list действительно может быть обновлен до такого значения.

Но это все равно не будет «нулевым» итератором.

person Nicol Bolas    schedule 12.01.2017

Вы должны понимать, что объект-итератор - это не совсем указатель. Это объект, который представляет положение элемента в структуре данных. Также увеличение конечного итератора не приводит к нулевому итератору. Это неопределенное поведение. Посмотрите Может ли итератор карты STL выйти из границы через приращение?

person Tapan Chugh    schedule 12.01.2017

Итератор не равен нулю, когда находится в конце списка, вместо этого он равен конечному итератору fl.end(). Поэтому оба итератора необходимо передать функции.

Внутренняя реализация итератора зависит от используемой библиотеки STL, поскольку std::forward_list его интерфейс таков, что он соответствует концепции ForwardIterator: http://en.cppreference.com/w/cpp/concept/ForwardIterator.

person tmlen    schedule 12.01.2017
comment
оба итератора должны быть переданы функции ‹- кажется анти-тематическим, когда речь идет о прямых связанных списках, не так ли? Разве однонаправленные связанные списки не должны иметь маркер конца? Предполагается, что мы сможем идти вперед, пока не дойдем до конца очереди. - person kmiklas; 12.01.2017
comment
Внутренне fl.end(), вероятно, представляет собой контрольное значение, и сравнение его с конечным итератором фактически проверяет, является ли указатель нулевым (в зависимости от того, как реализован std::forward_list). Но в STL для всех типов контейнеров всегда используются два итератора для перебора списка. - person tmlen; 12.01.2017