What is the difference between a const_iterator
and an iterator
and where would you use one over the other?
Minimal runnable examples
Non-const iterators allow you to modify what they point to:
std::vector v{0};
std::vector::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);
Const iterators don't:
const std::vector v{0};
std::vector::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 v;
void f() const {
std::vector::const_iterator it = this->v.begin();
}
void g(std::vector::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 v{0};
std::vector::iterator it = v.begin();
// non-const to const.
std::vector::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.