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_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).
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 fromiterator
- Add a constructor toconst_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
Conflict Between Copy Constructor and Forwarding Constructor
How to Create a Std::Set of Structures
Pointer Array and Sizeof Confusion
How to Set the Cout Locale to Insert Commas as Thousands Separators
Implementing a Std::Vector Like Container Without Undefined Behavior
Vector<Unique_Ptr<A> > Using Initialization List
C++11 Std::Mutex in Visual Studio 2012 Deadlock When Locked from Dllmain()
Boost Asio - How to Write Console Server
Are Variadic MACros Nonstandard
Does C++11 Allow Dollar Signs in Identifiers
Abstract Class VS Interface in C++
C++11 Std::Threads VS Posix Threads
Differencebetween "::" "." and "->" in C++
How to Hint the Optimizer by Giving the Range of an Integer
C++ Function for Picking from a List Where Each Element Has a Distinct Probability