Differencebetween Const_Iterator and Iterator

what is the difference between const_iterator and iterator?

There is no performance difference.

A const_iterator is an iterator that points to const value (like a const T* pointer); dereferencing it returns a reference to a constant value (const T&) and prevents modification of the referenced value: it enforces const-correctness.

When you have a const reference to the container, you can only get a const_iterator.

Edited: I mentionned “The const_iterator returns constant pointers” which is not accurate, thanks to Brandon for pointing it out.

Edit: For COW objects, getting a non-const iterator (or dereferencing it) will probably trigger the copy. (Some obsolete and now disallowed implementations of std::string use COW.)

What is the difference between const_iterator and non-const iterator in the C++ STL?

const_iterators don't allow you to change the values that they point to, regular iterators 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).

In C++, is const_iterator the same as const iterator?

No, they are not the same.

Like any const object, you can not make changes to a const iterator:

// ++it gives error below since we try to change it:
for(const std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {}

You are, however, allowed to change the value of the object a const iterator is pointing at:

// this is ok (assuming there is at least one element in the vector):
const std::vector<int>::iterator it = vec.begin();
*it = 10;

A const_iterator is mutable, but you can not change the object that the iterator is pointing at:

// ++it is ok below:
for(std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it) {
*it = 10; // error: `*it` is an `int const&`
}

With a const const_iterator, you can neither make changes to the iterator nor what it is pointing at.

const std::vector<int>::const_iterator it = vec.begin();
++it; // error
*it = 10; // error
std::cout << *it << '\n'; // ok

A constructed example to illustrate:

struct foo {
using const_iterator = char const*;
using iterator = char*;

const_iterator cbegin() const { return data; };
const_iterator cend() const { return data + sizeof data; };
const_iterator begin() const { return cbegin(); }
const_iterator end() const { return cend(); }
iterator begin() { return data; };
iterator end() { return data + sizeof data; };

char data[2];
};

As seen above, const_iterator and iterator are user defined type definitions. Only by convention are the names called what they are called. Using these conventional names also helpes when creating containers that are supposed to work well with other classes, since these type definitions are often used to create or specify instances/types. The names const_iterator and iterator do not give these alias any special properties though. It's all up to the creator of the class.

Should I prefer iterators over const_iterators?

I totally agree with you.
I think the answer is simple:
Use const_iterators where const values are the right thing to use, and vice versa.
Seems to me that those who are against const_iterators must be against const in general...

Does `const_iterator` really need to be a different class than `iterator`?

const keyword is not enough?

Actually, const keyword is too much: it forces you to write

const A::iterator it = a.cbegin();

which prevents you from using ++it later on.

You need to provide two separate classes, but it does not mean that you have to write the code twice. You can structure an implementation of your iterator in such a way that a common class that does all the work is embedded in both constant and non-constant iterator implementations, which expose the relevant methods of the embedded implementation to the callers.

const_iterator vs iterator for std::list

You are missing a few things described below, and the class is not "templetized" yet, but the approach is the same as what one implementation of the Standard Template Library is using.

  • Both iterators need a default constructor - this provides a way to make a null iterator, which you can assign later
  • const_iterator must be constructible from iterator - Add a constructor to const_iterator to accept "regular" iterator.

As far as code duplication is concerned, this is a fair observation indeed. However, most implementations fit on a single line, and return different types, so trying to share implementations across the two templates would make the code harder to read.



Related Topics



Leave a reply



Submit