Каково поведение std:: advance, когда вы говорите:
std::vector<int> foo(10,10);
auto i = foo.begin();
std::advance(i, 20);
Каково значение i? Это foo.end()?
Каково поведение std:: advance, когда вы говорите:
std::vector<int> foo(10,10);
auto i = foo.begin();
std::advance(i, 20);
Каково значение i? Это foo.end()?
Вы передаете размер foo
, продвигаясь на 20-ю позицию. Определенно это не конец вектора. Он должен вызывать поведение undefined при разыменовании, AFAIK.
Изменить 1:
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> foo(10,10) ;
std::vector<int>::iterator iter = foo.begin() ;
std::advance(iter,20);
std::cout << *iter << "\n" ;
return 0;
}
Выход: 0
Если это последний элемент вектора, тогда он должен был дать 10 на разыменование итератора. Итак, это UB.
Стандарт определяет std::advance()
в терминах типов итератора, в котором он используется (24.3.4 "Операции итератора" ):
Эти шаблоны функций используют + и - для итераторов произвольного доступа (и, следовательно, для них постоянное время); для входных, прямых и двунаправленных итераторов они используют ++ для обеспечения линейных временных реализаций.
Требования к этим операциям на разных типах итераторов также указаны в стандарте (в таблицах 72, 74, 75 и 76):
Для итератора ввода или пересылки
++r precondition: r is dereferenceable
для двунаправленного итератора:
--r precondition: there exists s such that r == ++s
Для итераторов с произвольным доступом операции +
, +=
, -
и -=
определяются в терминах префиксов двунаправленного и прямого итератора ++
и --
, поэтому те же предпосылки сохраняются.
Таким образом, продвижение итератора за пределы значения "прошлое-конец" (которое может быть возвращено функцией end()
в контейнерах) или продвигается перед первым разыменоваемым элементом допустимого диапазона итератора (как может быть возвращено begin()
на контейнере) - это поведение undefined, так как вы нарушаете предварительные условия операции ++
или --
.
Поскольку это поведение undefined вы не можете "ожидать" чего-либо в частности. Но вы, вероятно, столкнетесь в какой-то момент (надеюсь, скорее раньше, чем позже, так что вы можете исправить ошибку).
В соответствии со стандартом С++ и 24.3.4 std::advance(i, 20)
действует тот же эффект, что и for ( int n=0; n < 20; ++n ) ++i;
для положительного n
. С другой стороны (& sect; 24.1.3), если i
является сквозным, то операция ++i
undefined. Таким образом, результат std::advance(i, 20)
равен undefined.
На странице SGI для std:: advance:
Каждый итератор между я и я + n (включительно) неособо.
Поэтому я не является foo.end(), а разыменование приведет к поведению undefined.
Примечания:
Это, вероятно, поведение undefined. Единственное, что говорится в стандарте:
Поскольку только итераторы произвольного доступа предоставляют операторы + и -, библиотека предоставляет два шаблона функций вперед и расстояние. Эти шаблоны функций используют + и - для итераторов произвольного доступа (и, следовательно, для них постоянное время); для входных, прямых и двунаправленных итераторов они используют ++ для обеспечения линейных временных реализаций.
template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n);
Требуется: n должно быть отрицательным только для итераторов с двунаправленным и случайным доступом. Эффекты: Приращения (или уменьшения для отрицательного n) ссылки итератора я на n.