3

I was reading The C++ Programming Language 4th edition by Bjarne Stroustrup. In the iterator chapter (Chapter 31.1.2), it says:

Input iterator: We can iterate forward using ++ and read each element (repeatedly) using *.

Output iterator: We can iterate forward using ++ and write an element once only using *.

I have done many searches on whether input iterator can be read only once or repeatedly, for example: http://www.cplusplus.com/reference/iterator/InputIterator/ https://www.geeksforgeeks.org/input-iterators-in-cpp/

and most suggests that input iterator can be read once only. But why the author says repeatedly for the input iterator? Is this correct? And if so, why input iterator can be read repeatedly but output iterator can only be written once. I always thought input and output iterator are completely opposite of each other.

Thanks everyone!

0

3 Answers 3

3

The book is correct; and the contradicting sources are not. There appears to be no rule that disallows reading an object more than once by indirecting through an input iterator.

The other sources may be confused by another similar limitation which is that once input iterator has been incremented, all copies of the previous iterator are invalidated, and thus may not be indirected anymore. This limitation is shared by output iterators. By example:

value = *inputIt;
value = *inputIt; // OK
copyIt = inputIt;
++inputIt;
value = *copyIt;  // Not OK

The book is also correct that output iterator does have the limitation:

 *outputIt = value;
  ++outputIt;
 *outputIt = value; // OK
 *outputIt = value; // Not OK

I always thought input and output iterator are completely opposite of each other.

Many output iterators are also input iterators, so "opposite" isn't exactly very descriptive. They are partially overlapping sets of requirements. An iterator can meet both sets of requirements.

If we have *outputIt = 1; then *outputIt = 2; aren't we just assigning to the same *outputit twice?

Yes; And that's something that output iterators are not required to support.

Consider for example an output iterator that sends packets over the internet. You've written a packet, and it has been sent to the internet and received by some other machine. You can't travel back in time and decide that the packet that was sent is something different. You must move on to the next packet and send that instead.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for your answer. How about the output iterator. for example writing *outputIt = value; twice like your example is not OK/will not compile?
@user9607441 *outputIt = value; *outputIt = value; would not be OK. It would compile, since it is well formed, but the behaviour doesn't need to be well defined (it can be, depends on how the iterator has been defined).
@user9607441 It's important to understand that, in c++, something can both compile and not be OK at the same time.
Thanks everyone...I'm still confused on why the second *outputIt = value; is not OK?If we have *outputIt = 1; then *outputIt = 2; aren't we just assigning to the same *outputit twice? What prevents us from doing that, and what kinds of "undefined behaviors" will this cause?
@user9607441 I added an example to describe why it's not OK.
|
2

Bjarne's quote is correct. If you have an input iterator you can do *iterator as many times as you want. If you have an output iterator you can only do *iterator once.

What they both have in common though is they can only be used in single pass algorithms. Once you increment either an input or output iterator then an iterator to a previous position is no longer required to be dereferenceable

That means in

while (iterator != end)
{
    if (*iterator == some_value)
        something = *iterator;
    ++iterator;
}

iterator has to be an input iterator since we dereference it twice each iteration. On the other hand

while (iterator != end)
{
    something = *iterator;
    ++iterator;
}

works for both an input and output iterators since we do only a single dereference.

5 Comments

Thank you for your answer! but why output iterator can only be dereferenced once while input Iterator can be dereference multiple times before++ without causing any "undefined behaviors"
@user9607441 It is just what the standard permits. An implementation can allow an output iterator to be dereferenced multiple times but the standard doesn'y force that on the implementation. Why exactly I'm not sure but it probably related to writing to output streams where they only expect to get a single value per element.
Thank you @NathanOliver! I think I understand it now. So the standard explicitly says output iterator can only be read once but doesn't put this restriction on the input iterator?
@user9607441 Yes. The standard says you can only safely dereference an output iterator once. It does not put that caveat on an input iterator so you are allowed to dereference as many times as you want.
dereferencing once for output itetator, not writing? EDIT: I got it. The only valid use of an operator* is on the left side of the assignment statement.timsong-cpp.github.io/cppwp/n3337/output.iterators
1

You can read through an input iterator as many times as you want to. That comes from the requirement that "(void)*a, *a is equivalent to *a" [input.iterators], see table.

You can only write through an output iterator once. For *r = o, "After this operation r is not required to be dereferenceable". [output.iterators], see table. After you increment r you have a new iterator, and you can again assign through it once.

Once you combine these two into a forward iterator, the restriction on multiple assignments through the same iterator goes away.

1 Comment

Thank you @Pete Becker! I just found your references in the standard documentation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.