3

Is a const_iterator the same as const iterator? if not what's the difference? if yes why does standard use const_iterator when const iterator is already meaningful?

For example, are these two declarations exactly the same ?

string& replace (const_iterator i1, const_iterator i2, const string& str);

string& replace (const iterator i1, const iterator i2, const string& str);

Sad egg
  • 79
  • 1
  • 9
  • 4
    The difference is analogous to `const T *` vs `T * const` vs `const T * const`. A `const_iterator` can't be used to change the referred thing but you can change which thing it refers. `const iterator` can change the thing being referred, but you can't change which thing it refers to. – François Andrieux Nov 18 '21 at 23:40
  • https://stackoverflow.com/questions/309581/what-is-the-difference-between-const-iterator-and-non-const-iterator-in-the-c this may help you – Ryan Millares Nov 18 '21 at 23:41

1 Answers1

7

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.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • So can we say, a `const_iterator it` is the same as `iterator const it` ? How about `const const_iterator it` and `const iterator const it` ? – Sad egg Nov 20 '21 at 19:59
  • @Sadegg `const_iterator it` and `iterator const it` are very different as I tried to describe. Perhaps the placement of `const` is what is making it messy? I agree if that's the case. `const` applies to what's left of it. If there is nothing to the left, it applies to the first thing to the right of it. Someone must have been on something when coming up with that. – Ted Lyngmo Nov 20 '21 at 22:43
  • "_How about `const const_iterator it` and `const iterator const it`_" - They are also different and the second one has a redundant `const`. Both `const`s in the second one aim at the `iterator` because of the confusing rule I mentioned above. – Ted Lyngmo Nov 20 '21 at 22:50