Минимальные примеры
Неконстантные итераторы позволяют вам изменять то, на что они указывают:
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);
Const итераторы не:
const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
Как показано выше, v.begin()
перегружен const
и возвращает либо iterator
, либо const_iterator
в зависимости от постоянства переменной контейнера:
Распространенный случай, когда всплывает const_iterator
, это когда this
используется внутри метода const
:
class C {
public:
std::vector<int> v;
void f() const {
std::vector<int>::const_iterator it = this->v.begin();
}
void g(std::vector<int>::const_iterator& it) {}
};
const
составляет this
const, что составляет this->v
const.
Обычно вы можете забыть об этом с помощью auto
, но если вы начнете передавать эти итераторы, вам нужно будет подумать о них для сигнатур методов.
Так же, как const и не-const, вы можете легко конвертировать из не-const в const, но не наоборот:
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
// non-const to const.
std::vector<int>::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;
Какой использовать: аналогично const int
против int
: предпочитайте const-итераторы всякий раз, когда вы можете их использовать (когда вам не нужно изменять контейнер с ними), чтобы лучше документировать ваше намерение чтения без изменения .