Давайте разберем эту команду и посмотрим, что происходит:
*out_iter++ = *in_iter++;
Это также может быть записано следующим образом, в соответствии с приоритетом оператора :
// read next value, but return unmodified iterator (with the previous value)
// the first value is read when the iterator is constructed!
auto x = in_iter++;
// get value that was previously read
const auto res = *x;
// print this value
*out_iter++ = res;
Таким образом, в основном это печатает значение только после чтения следующего. Для ввода "a b c"
происходит следующее:
- конструктор
istream_iterator<string> in_iter(cin)
читает "a"
auto x = in_iter++;
читает "b"
, но возвращает итератор, содержащий "a"
const auto res = *x;
приводит к "a"
, который затем печатается. auto x = in_iter++;
читает "c"
, но возвращает итератор, содержащий "b"
const auto res = *x;
приводит к результату "b"
, который затем печатается. auto x = in_iter++;
пытается что-то прочитать, но потоковый буфер пуст, поэтому он ожидает дальнейшего ввода.
Пока было напечатано только "a b"
, а "c"
«застряло» в in_iter
.
Если бы поток содержал [eof]
(например, если бы вы каким-то образом завершили поток), шаг 6 был бы другим и шаг 7 (и 8) произойдет:
auto x = in_iter++;
читает
[eof]
, становится eof-итератором и возвращает итератор, содержащий
"c"
const auto res = *x;
, в результате получается
"c"
, который затем печатается. l oop завершается
Таким образом, этот код не является неправильным, он просто не делает того, что можно было бы интуитивно ожидать.
Ваш код, с другой стороны, делает следующее :
// extract first value that was read by the constructor and "prepare" to print
*out_iter = *in_iter;
// read next value
out_iter++;
// print value
in_iter++;
Это работает, как ожидалось, потому что оно печатает старое значение перед тем, как считывает новое.