about const iterators 2

i have seen a const iterator defined as this:

const_iterator cend() const noexcept { return const_iterator(end_); }

why are there 2 const expressions ?

what does the expression const_iterator

infront of cend() mean

and what does the expression "const" after

const_iterator cend() "const" mean ?


The keyword const only appears once in that line, immediately before noexcept. It means that "this member function doesn't allow the logical state of the container to change".

This allows you to call cend() on (for example) a vector defined as
const vector<int> v{1, 2, 3}; v.cend(); // works fine . If cend() wasn't a const member function, then the compiler would assume that it would be possible to change the const vector v by calling cend(), and so it would cause an compile-time error.

The const in part of the typename const_iterator alludes to the fact that you may not change the data the iterator refers to (although you may change the iterator). My guess is that much of the confusion comes from the differences between iterator, const_iterator, iterator const, and const_iterator const. The differences are similar to those between T*, T const*, T* const, and T const* const, because an iterator is a generalized kind of pointer.

Q: How do we write a pointer to constant int?
A: int const* ptr = &cfoo; // const before the star; const applies to the type being pointed-to
Q: What if we want a pointer to int, but want the pointer itself to be constant?
A: int* const ptr = &foo; // const after the star; const applies to the pointer

The same idea applies to iterators:
| Declaration               | Can change *ptr? | Can change ptr? |
| T* ptr                    | Yes              | Yes             |
| T const* ptr              | No               | Yes             |
| T* const ptr              | Yes              | No              |
| T const* const ptr        | No               | No              |
|---------------------------+------------------+-----------------|
| Declaration               | Can change *iter | Can change iter |
| iterator iter             | Yes              | Yes             |
| const_iterator iter       | No               | Yes             |
| iterator const iter       | Yes              | No              |
| const_iterator const iter | No               | No              |


In English, the line in question could be read something like the following:
const_iterator cend() const noexcept { return const_iterator(end_); }
Let cend be a member function of (some container). It accepts no parameters, and returns a mutable iterator through which the elements of this container cannot be changed (the type named container::const_iterator). The returned iterator refers to the end of the container. This member function may be called when the elements of this container cannot be changed (because *this is const), and it is guaranteed to never throw exceptions.


Note: When you say "const expressions" it could be taken to mean a "constant expression", which is something entirely different. Technically speaking, const is a qualifier, along with volatile:
http://en.cppreference.com/w/cpp/language/cv
Topic archived. No new replies allowed.