What's the recommended way of iterating a container in C++11?
Using
container.begin() and container.end()
Or
begin(container) and end(container)
If any, when is one preferred over the other?
An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.
An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualised as something similar to a pointer pointing to some location and we can access content at that particular location using them.
Iterators play a critical role in connecting algorithm with containers along with the manipulation of data stored inside the containers. The most obvious form of an iterator is a pointer. A pointer can point to elements in an array and can iterate through them using the increment operator (++).
An iterator is an object that points to an element inside a container. Like a pointer, an iterator can be used to access the element it points to and can be moved through the content of the container. Each container in the C++ Standard Library provides its own iterator, as well as some methods to retrieve it.
I think the new syntax with range based for loops
for (auto item : container)
is probably the most C++11 like.
As others commented, you sometimes want auto&
or const auto&
instead of auto
.
The better way is
begin(container)
end(container)
because it's more extensible. For example, template argument deduction can be used to determine the size of a static array and hence begin(my_static_array)
and end(my_static_array)
will work.
More generally, you can add overloads/specialisations to begin(.) end(.) and use immutable legacy types in generic algorithms.
You really only need to worry about this if you're writing a generic algorithm youself
template <typename T>
void foo (T & t)
{
bar (begin(t), end(t)); // certainly better than bar(t.begin(), t.end())
}
In client code it doesn't matter so much. In fact, I would say don't use the new form in that case -- I like to reserve certain styles/idioms for certain circumstances, divide my mindsets. But that's just me.
for (auto i = c.begin(); i != c.end(); ++i)
// I can see at-a-glance that c is a STL-style container.
// That might be useful to know. I can probably dismiss static arrays
// and unorthodox containers as possibilities.
foo (i, c.size());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With