Iterators of the categories forward, bidirectional, and random access need to be default-constructible.
Why is this, and why do input and output operators not have to be default-constructible?
Forward iterators and stronger are required to refer to some external sequence (see [forward.iterators]/6 which says "If a
and b
are both dereferenceable, then a == b
if and only if *a
and *b
are bound to the same object.")
This means they are generally just a lightweight handle onto something else (e.g. a pointer to an element or a node in a container) and so there is little reason not to require that they can be default constructed (even if default construction creates a singular iterator that can't be used for anything until assigned a new value). It's possible for all non-pathological* forward iterators to support default construction, and relying on that makes some algorithms easier to implement.
Iterators which only meet the input iterator or output iterator requirements (and nothing stronger) might contain state within themselves which is modified by operator++
and so it might not be possible for that state to be default-constructed. No algorithm that only operates on input/output iterators needs to default construct them, so it isn't required.
- spot the "no true scotsman" argument here ;)
Input/Output iterators:
Input Iterator: once an InputIterator i has been incremented, all copies of its previous value may be invalidated.
Output Iterator: After this operation r is not required to be dereferenceable and any copies of the previous value of r are no longer required to be dereferenceable or incrementable.
If we look at this it seems clear that these iterators are designed to be used in the simplest method possible. Much like an array index or simple pointer would be used for single-pass algorithms. There is therefore really no need to have default constructors.
Note however that just because default constructors is not required technically doesn't disqualify you from implementing them if you want.
These are the first level of iterators that require default constructors but why?
There are many reasons related to historical programming reasons ect and I believe this is all to some extent valid. In a certain way I think the committee figured somewhere between iterator and randomAccessIterator default construction was required to be implemented and forward iterators seemed like the best choice.
There is however one fairly good reason why:
Forward iterators support multi-pass algorithms and therefore require that copies of the iterator are still valid after the iterator has been used/incremented. If these copies are valid still it means the algorithm would allow us to "save" them somewhere. Which also means the iterator where we save them needs to have a default/initial value.
Consider:
class MyClass
{
public:
void myFunction(ForwardIterator &i)
{
//do some code here
savedIter = i;
//do some code here
}
private:
ForwardIterator savedIter;
}
By definition this is valid because we are allowed to save the iterator for some amount of time as the requirement is that copies of this iterator will remain valid. (At least until the data structure the iterator points to is destroyed)
However for this class to be created ForwardIterator requires a default constructor obviously...
Forward / bidirectional / random access iterators can often be pointers - it would historically have aided migration from pointer-using code to iterators if the construction and initialisation could be left delocalised if that was the way the code happened to be. Forcing more wholesale change would have frustrated a lot of people trying to migrate older code off explicit use of pointers and onto iterators. Changing it would now break a lot of code.
Input and output operators are often most elegantly implemented with references to underlying stream or other I/O objects, and references must be initialised at construction. Of course, implementations could be forced to defer that, and use pointers internally, but that's sure to rub some people up the wrong way - seeming too "C"-like - so it's unsurprising the Standard facilitates use of references.
来源:https://stackoverflow.com/questions/28832492/why-do-iterators-need-to-be-default-constructible