.begin()
returns an iterator that “points” to the first element
.end()
returns an iterator that “points” one past the last element
.begin()
and .end()
vector<int> v = {11, 22, 33, 44, 55}; for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << *it << ' ';
11 22 33 44 55
or:
vector<int> v = {11, 22, 33, 44, 55}; for (auto it = v.begin(); it != v.end(); ++it) cout << *it << ' ';
11 22 33 44 55
++it
is probably faster than it++
.
const
Why does this fail?
class Foo { int sum() const { int total = 0; for (vector<int>::iterator it = data.begin(); it != data.end(); ++it) total += *it; return total; } vector<int> data; };
c.cc:4: error: conversion from '__normal_iterator<const int*,[...]>' to non-scalar type '__normal_iterator<int*,[...]>' requested
const
.sum()
is a const
method.
.sum()
, data
is a const vector<int>
.
const
method implemented, anyway?
const
method.
const
when compiling a const
method.
data.begin()
and data.end()
return iterators
of type const_iterator
, not type iterator
.
const_iterator
to iterator
.
This is the same problem:
const vector<int> v = {11, 22, 33, 44, 55}; for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) cout << *it << ' ';
c.cc:2: error: conversion from '__normal_iterator<const int*,[...]>' to non-scalar type '__normal_iterator<int*,[...]>' requested
One solution—use the correct type:
const vector<int> v = {11, 22, 33, 44, 55}; for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) cout << *it << ' ';
11 22 33 44 55
A better solution—let auto
figure it out:
const vector<int> v = {11, 22, 33, 44, 55}; for (auto it = v.begin(); it != v.end(); ++it) cout << *it << ' ';
11 22 33 44 55
The best solution—avoid all of this:
const vector<int> v = {11, 22, 33, 44, 55}; for (auto val : v) cout << val << ' ';
11 22 33 44 55
.cbegin()
and .cend()
.begin()
is an overloaded method. It returns a const_iterator
if the object is const
, iterator
otherwise.
.end()
is an overloaded method. It returns a const_iterator
if the object is const
, iterator
otherwise.
.cbegin()
: like .begin()
, but always returns const_iterator
.cend()
: like .end()
, but always returns const_iterator
vector<int> v = {11, 22, 33, 44, 55}; for (auto it = v.cbegin(); it != v.cend(); ++it) cout << *it << ' ';
11 22 33 44 55
.rbegin()
and .rend()
.rbegin()
: like .begin()
, but goes the other way
.rend()
: like .end()
, but goes the other way
.crbegin()
: like .cbegin()
, but goes the other way
.crend()
: like .cend()
, but goes the other way vector<int> v = {11, 22, 33, 44, 55}; for (auto it = v.rbegin(); it != v.rend(); ++it) cout << *it << ' ';
55 44 33 22 11
vector<int> v = {11, 22, 33, 44, 55}; for (auto it = v.crbegin(); it != v.crend(); ++it) cout << *it << ' ';
55 44 33 22 11
forward_list
, as a singly-linked list,
doesn’t have reverse iterators.
iterator
and const_iterator
are the same.
set
has inherently-constant iterators, because it’s in order.
If you could change the values via iterators, then it wouldn’t be in
order any more.
unordered_set
, a hash, has its own special order, and
changing the values in place would be bad.
How about old C-style data?
int a[] = {11, 22, 33, 44, 55}; for (auto it = a.begin(); it != a.end(); ++it) cout << *it << ' ';
c.cc:2: error: request for member 'begin' in 'a', which is of non-class type 'int [5]'
That failed miserably. Perhaps it’s because arrays are not objects.
Fortunately, there exist begin()
and end()
free functions (not methods).
int a[] = {11, 22, 33, 44, 55}; for (auto it = begin(a); it != end(a); ++it) cout << *it << ' ';
11 22 33 44 55
These work for objects, as well:
set<int> s = {11, 22, 33, 44, 55}; for (auto it = begin(s); it != end(s); ++it) cout << *it << ' ';
11 22 33 44 55
What use is that? Generality for the sake of generality?
Consider any for loop:
forward_list<int> fl = {11,22,33,44,55}; for (double v : fl) cout << v << ' ';
11 22 33 44 55
The compiler turns this into:
forward_list<int> fl = {11,22,33,44,55}; const auto toofar = end(fl); for (auto it = begin(fl); it != toofar; ++it) { double v = *it; cout << v << ' '; }
11 22 33 44 55
Which works for any container type, even C-style arrays.