В примере кода я часто вижу такой код, как *it++
для итераторов вывода. Выражение *it++
создает копию it
, увеличивает it
, а затем возвращает копию, которая окончательно разыменовывается. Насколько я понимаю, создание копии выходного итератора делает недействительным источник. Но тогда приращение it
, которое выполняется после создания копии, будет незаконным, верно? Является ли мое понимание итераторов вывода ошибочным?
Как *it++ действителен для итераторов вывода?
Ответы (5)
Выражение *it++
не (должно) делать его копию, не увеличивать его и т. д. Это выражение допустимо только для удобства, так как следует обычной семантике . Только operator=
выполняет фактическую работу. Например, в g++ реализация ostream_iterator
, operator*
, operator++
и operator++(int)
делает только одну вещь: return *this
(другими словами, ничего!). Мы могли бы написать, например:
it = 1;
it = 2;
*it = 3;
++it = 4;
Вместо: *it++ = 1; *it++ = 2; *it++ = 3; *it++ = 4;
ostream_iterator
. Так что в общем случае не может требоваться, чтобы *it++
делал копию и т.д.
- person rafak; 28.10.2010
while (first != last) *result++ = *first++;
Тот факт, что ваши примеры, it = 2;
, *it = 3;
и ++it = 4;
, работают из-за реализации, а не потому, что это указано в стандарте.
- person Dingo; 29.10.2010
*result
или result++
... Когда я прочитал часть операции ostream_iterator (24.5.2.2), я интерпретировал отсутствие Спецификация Эффектов как: ничего не делает.
- person rafak; 29.10.2010
Стандарт требует, чтобы *r++ = t
работало для итераторов вывода (24.1.2). Если это не работает, это не итератор вывода по стандартному определению.
Реализация итератора должна убедиться, что такие операторы работают правильно внутри.
Причина, по которой вам не следует хранить несколько копий выходного итератора, заключается в том, что он имеет однопроходную семантику. Итератор может быть разыменован только один раз для каждого значения (т. е. он должен увеличиваться между каждой операцией разыменования). Как только итератор разыменован, его копия не может быть.
Вот почему *r++ = t
работает. Создается копия исходного итератора, исходный итератор разыменовывается, а копия увеличивается. Исходный итератор больше никогда не будет использоваться, а копия больше не будет ссылаться на то же значение.
*r++ = t
- это то, как вы используете итератор вывода. Наоборот даже не требуется компилировать.
- person aschepler; 23.10.2010
Выходные итераторы просто не работают как обычные итераторы, и их интерфейс указан так, что их можно использовать в выражениях, подобных указателям (*it++ = x
), с полезными результатами.
Как правило, operator*()
, operator++()
и operator++(int)
все возвращают *this
в качестве ссылки, а итераторы вывода имеют магический operator=
, который выполняет ожидаемую операцию вывода. Поскольку вы не можете читать из выходного итератора, тот факт, что operator*()
и т. д. не работают, как для других итераторов, не имеет значения.
Глядя на ваш комментарий, кажется, что большая часть путаницы возникает из-за документации SGI, которая, я бы сказал, немного вводит в заблуждение в этом вопросе.
Копирование выходного итератора не делает скопированный итератор недействительным. Реальное ограничение довольно простое: вы должны разыменовывать заданное значение выходного итератора только один раз. Однако наличие двух копий одновременно — это нормально, если вы разыменовываете только одну из них, пока они имеют одинаковое значение. В случае, подобном тому, когда вы разыменовываете один, затем отбрасываете его значение и увеличиваете другой, но разыменовываете его только после того, как произошло приращение, все прекрасно.
Разве итератор не просто указатель? Увеличение, а затем разыменование просто переходит к следующему элементу.
vector<int>::iterator it(container.begin());
- person Adrian McCarthy   schedule 23.10.2010out_iterator a(b);
b
может быть недопустимым в документации SGI, как вы сказали, но в C++03 на это не намекает. Но поскольку и на странице SGI, и в C++03 явно указано, что выражение*it++ = value
должно быть допустимым, это требование перевешивает любые другие проблемы, связанные с таким использованием. - person aschepler   schedule 23.10.2010