Reputation: 40947
What is the difference between a const_iterator
and an iterator
and where would you use one over the other?
Upvotes: 177
Views: 126169
Reputation: 247909
They should pretty much be self-explanatory. If iterator
points to an element of type T
, then const_iterator
points to an element of type const T
.
It's basically equivalent to the pointer types:
T* // A non-const iterator to a non-const element. ≡ vector<T>::iterator
T* const // A const iterator to a non-const element. ≡ const vector<T>::iterator
const T* // A non-const iterator to a const element. ≡ vector<T>::const_iterator
A const
iterator
always points to the same element, so the iterator itself is const
. But the element it points to does not have to be const
, so the element it points to can be changed.
A const_iterator
is an iterator that points to a const
element, so while the iterator itself can be updated (incremented or decremented, for example), the element it points to cannot be changed.
Upvotes: 52
Reputation: 382552
Minimal runnable examples
Non-const iterators allow you to modify what they point to:
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);
Const iterators don't:
const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
As shown above, v.begin()
is const
overloaded, and returns either iterator
or const_iterator
depending on the const-ness of the container variable:
A common case where const_iterator
pops up is when this
is used inside a const
method:
class C {
public:
std::vector<int> v;
void f() const {
std::vector<int>::const_iterator it = this->v.begin();
}
void g(std::vector<int>::const_iterator& it) {}
};
const
makes this
const, which makes this->v
const.
You can usually forget about it with auto
, but if you starting passing those iterators around, you will need to think about them for the method signatures.
Much like const and non-const, you can convert easily from non-const to const, but not the other way around:
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
// non-const to const.
std::vector<int>::const_iterator cit = it;
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
// Compile time error: no conversion from const to no-const.
//it = ci1;
Which one to use: analogous to const int
vs int
: prefer const iterators whenever you can use them (when you don't need to modify the container with them), to better document your intention of reading without modifying.
Upvotes: 10
Reputation: 8186
ok Let me explain it with very simple example first without using constant iterator consider we have collection of random integers collection "randomData"
for(vector<int>::iterator i = randomData.begin() ; i != randomData.end() ; ++i)*i = 0;
for(vector<int>::const_iterator i = randomData.begin() ; i!= randomData.end() ; ++i)cout << *i;
As can be seen for writing/editing data inside collection normal iterator is used but for reading purpose constant iterator has been used . If you try using constant iterator in first for loop you will get error . As a thumb rule use constant iterator to read data inside collection .
Upvotes: 0
Reputation: 373
Unfortunaty, a lot of the methods for the STL containers takes iterators instead of const_iterators as parameters. So if you have a const_iterator, you can't say "insert an element before the element that this iterator points to" (saying such a thing is not conceptually a const violation, in my opinion). If you want do that anyway, you have to convert it to a non-const iterator using std::advance() or boost::next(). Eg. boost::next(container.begin(), std::distance(container.begin(), the_const_iterator_we_want_to_unconst)). If container is a std::list, then the running time for that call will be O(n).
So the universal rule to add const wherever it is "logical" to do so, is less universal when it comes to STL containers.
However, boost containers take const_iterators (eg. boost::unordered_map::erase()). So when you use boost containers you can be "const agressive". By the way, do anyone know if or when the STL containers will be fixed?
Upvotes: 8
Reputation: 74430
(as others have said) const_iterator doesn't allow you modify the elements to which it points, this is useful inside of const class methods. It also allows you to express your intent.
Upvotes: 0
Reputation: 73433
Use const_iterator whenever you can, use iterator when you have no other choice.
Upvotes: 7
Reputation: 99751
const_iterator
s don't allow you to change the values that they point to, regular iterator
s do.
As with all things in C++, always prefer const
, unless there's a good reason to use regular iterators (i.e. you want to use the fact that they're not const
to change the pointed-to value).
Upvotes: 162