Can std::vector::iterator simply be T*?

2019-07-04 11:42发布

问题:

Simple theoretical question: would a simple pointer be a valid iterator type for std::vector?

For other containers (e.g. list, map), that would not be possible, but for std::vector the held data is guaranteed to be contiguous, so I see no reason why not.

As far as I know, some implementations (e.g. Visual Studio) do some safe checks on debug build. But that is in UB territory, so for well defined behavior I think there is no difference.

Apart for some checks ("modifying" undefined behavior), are there any advantages of using a class instead of a simple pointer for vector iterators?

回答1:

would a simple pointer be a valid iterator type for std::vector?

Yes. And also for std::basic_string and std::array.

are there any advantages of using a class instead of a simple pointer for vector iterators?

It offers some additional type safety, so that logic errors like the following don't compile:

std::vector<int> v;
int i=0;
int* p = &i;
v.insert(p, 1); // oops, not an iterator!
delete v.begin();  // oops!

std::string s;
std::vector<char> v;
// compiles if string and vector both use pointers for iterators:
v.insert(s.begin(), '?');
std::array<char, 2> a;
// compiles if array and vector both use pointers for iterators:
v.erase(a.begin());


回答2:

Yes, it can be T*, but that has the slightly annoying property that the ADL-associated namespace of std::vector<int>::iterator is not std:: ! So swap(iter1, iter2) may fail to find std::swap.



回答3:

A food for thought - an iterator class can also be implemented by the terms of indexes instead of pointers

of course, when a vector reallocates, all the pointers , references and iterators become invalidated.

but at least for iterators, that doesn't have to be the case always, if the iterator holds an index + pointer to the vector, you can create non-reallocation-invalidated iterators that simply returns (*m_vector)[m_index]. the iterator is invalid when the vector dies out, or the index is invalid. in other words, the iterator is invalid only if the term vec[i] is invalid, regardless of reallocations.

this is a strictly non standard implementation of a vector iterator, but non the less an advantage to class based iterator rather than raw pointer.

also, UB doesn't state what should happen when an invalid iterator is being dereferenced. throwing an exception or logging an error fall under UB. that means that an iterator which does bound checking is significantly slower, but for some cases where speed is not important, "safe but slow iterator" may have more advantages than "unsafe but fast iterator"