Should I prefer iterators over const_iterators?

Someone recently cited an article by Scott Meyers that says:

  • Prefers iterators over const_iterators ( pdf link ).

Someone else commented that the article was probably out of date. I wonder what your opinions are?

Here is my. One of the main points of the article is that you cannot erase or paste on const_iterator , but it’s funny to use this as an argument against const_iterators . I thought that all this means that you do not change the range at all, neither the elements themselves, replacing their values, nor the range, inserting or erasing. Or am I missing something?

+27
c ++ iterator stl const-iterator
Apr 19 '09 at 11:28
source share
6 answers

I totally agree with you. I think the answer is simple: Use const_iterators where const values ​​are correct, and vice versa. It seems to me that those who are against const_iterators should be against const in general ...

+22
Apr 19 '09 at 11:34
source share

Here is a slightly different way to look at it. Const_iterator almost never makes sense when you pass it as a pointer to a specific collection and which you pass also to collections. Mr. Meyer specifically pointed out that Const_iterator cannot be used with most member functions of an instance of a collection. In this case, you will need a simple iterator . However, if you do not have a collection descriptor, the only difference between them is that you can change what iterator points to, and you cannot change the object referenced by Const_iterator .

So ... you want to use iterator whenever you pass a collection and put it in a collection in an algorithm. In principle, such signatures as:

 void some_operation(std::vector<int>& vec, std::vector::const_iterator pos); 

don't make much sense. The implicit statement is that some_operation can modify the base collection, but it does not have the right to modify pos links. That doesn't make much sense. If you really want this, then pos should be an offset instead of an iterator.

On the other hand, most algorithms in STL are based on ranges specified by a pair of iterators. The collection itself is never passed, so the difference between iterator and Const_iterator is whether it is possible to change the value in the collection through an iterator or not. Without reference to the collection, the separation is pretty clear.

Hope this made it as clear as dirt;)

+9
Apr 19 '09 at 15:31
source share

I do not think this particular Mayer expression should be taken with particular care. If you want to perform the operation without modification, it is better to use const_iterator . Otherwise, use a regular iterator . However, pay attention to one important thing: never mix iterators, i.e. const with non-const tags. As long as you know the latter, you should be fine.

+3
Apr 19 '09 at 11:40
source share

I generally prefer a constant, but I recently ran into a riddle with const_iterators, which confused my philosophy of "always use const":

 MyList::const_iterator find( const MyList & list, int identifier ) { // do some stuff to find identifier return retConstItor; } 

Since passing a list of constants in the link requires that I use only const iterators, now if I use find, I can do nothing with the result, but look at it, although all I wanted to do was express that find would not change rolling list.

It may be interesting, then, if the advice of Scott Myers will deal with such problems when it becomes impossible to avoid conscience. From what I understand, you cannot (reliably) un-const const_iterators with a simple cast due to some internal details. This is also a (possibly cumulative) problem.

this is probably true: How to remove the const_iterator constant?

+3
Oct 12 '09 at 21:57
source share

In my reading of this link, Meyers seems to be fundamentally saying that interator is better than const_interator, because you cannot make changes through const_iterator.

But if this is what he says, then Meyers is actually mistaken. That is why const_iterator is better than an iterator when this is what you want to express.

+2
Apr 19 '09 at 18:21
source share

C ++ 98

I think you need to consider that the Meyers statement refers to C ++ 98. It's hard to say today, but if I remember correctly

  • it was just not easy to get a const_iterator for a non const container at all
  • If you have a const_iterator, you could hardly use it, since most position arguments (for all?) For the container member functions should have been iterators, not const_iterators

eg.

 std::vector<int> container; 

would take

 static_cast<std::vector<int>::const_iterator>(container.begin()) 

to get a const_iterator that would greatly inflate a simple .find, and even if you had your result, then

 std::vector<int>::const_iterator i = std::find(static_cast<std::vector<int>::const_iterator>(container.begin()), static_cast<std::vector<int>::const_iterator>(container.end()),42); 

it would not be possible to use your std :: vector :: const_iterator to insert into a vector or any other member function that would expect iterators for a position. And there was no way to get an iterator from a constant iterator. There is no casting method for this (exists?).

Since a constant iterator does not mean that the container cannot be changed, but only the element that it points to cannot be changed (the constant iterator is the equivalent of a pointer to const) , which was a really big bunch of crap that you have to deal with cases.

Today the opposite is true.

const iterators are easy to get with cbegin, etc. even for non const containers and all (?) member functions that take positions have constant iterators as their arguments, so there is no need for any conversion.

 std::vector<int> container; auto i = std::find(container.cbegin(), container.cend(), 42); container.insert(i, 43); 

So what once was

Prefer iterators over const_iterators

today really really should be

Prefer const_iterators over iterators

since the first is simply an artifact of historical implementation deficits.

+2
Aug 22 '17 at 19:25
source share



All Articles