The begin() and cbegin() functions are used to return an iterator pointing to the first element of a container like a vector, list, or map in C++. The difference between them lies in the type of iterator they return and the const-qualification of the object they are called on1.


“Talking to begin() is like chatting with a friend, you can share and change stories. But talking to cbegin() is like talking to a librarian, you can only read the stories, no editing allowed!” 😄

Here’s the difference:

  • begin(): This function returns an iterator or a const_iterator depending on the const-qualification of the object it is called on2. If the object is non-const, begin() returns an iterator, allowing modification of the vector elements2. If the object is const, begin() returns a const_iterator2.
std::vector<int> vec;
const std::vector<int> const_vec;

vec.begin(); // Returns an iterator
const_vec.begin(); // Returns a const_iterator
std::vector<int> vec;
const std::vector<int> const_vec;

vec.cbegin(); // Returns a const_iterator
const_vec.cbegin(); // Returns a const_iterator

In summary, if you know you need a const_iterator, call cbegin(). If you know you need an iterator, call begin() and you’ll get an error if it’s not valid. If you don’t care, call begin().

Still confused about the const_iterator

In C++, an iterator is like a pointer that is used to point to an element in a container (like an array or a vector). Now, there are two types of iterators: regular iterators and const_iterators3.

  • Regular Iterator: This is just like a normal pointer. You can use it to read or modify the element it points to.
  • Const Iterator: This is a special type of iterator. It points to an element, but it treats this element as if it were constant. This means that you can use a const_iterator to read an element, but you cannot use it to modify the element. It’s like a ‘read-only’ pointer.

Here’s an analogy: Imagine you’re at a museum. A regular iterator is like being able to touch and move the exhibits. A const_iterator, on the other hand, is like having to look at the exhibits from behind a glass barrier. You can see them (read), but you can’t touch or move them (modify).

In C++, many Standard Template Library (STL) containers provide const_iterator. Here are some of them:

  1. std::vector
  2. std::list
  3. std::map
  4. std::set
  5. std::multimap
  6. std::multiset
  7. std::unordered_map
  8. std::unordered_set
  9. std::unordered_multimap
  10. std::unordered_multiset
  11. std::string
  12. std::array
  13. std::deque

These containers provide two member functions: cbegin() and cend() that return a const_iterator to the beginning and end of the container, respectively. You can use these const_iterators to traverse the container, but they only allow you to read the value, not modify it.

Getting more deeper into concepts, HEHE😁

  1. Performance Implications: While iterators and const_iterators have the same performance characteristics, using const_iterators where possible can help catch potential bugs at compile-time. If you try to modify an element through a const_iterator, the compiler will catch the error, whereas with a non-const iterator, the error might only be caught at runtime.
  2. Const-Correctness: Using const_iterators when you don’t need to modify the container elements is a good practice that follows the principle of “const-correctness”. It makes your code more readable, maintainable, and less prone to accidental modifications.
  3. Overloaded Functions: Sometimes, member functions of containers are overloaded based on whether they return an iterator or a const_iterator. For example, std::vector::at() has two overloads: one that returns a reference when called on a non-const vector, and another that returns a const reference when called on a const vector.
  4. Range-based for loops: When using range-based for loops (for (auto& elem : container)), the type of the loop variable (elem) depends on the type of iterator returned by begin() and end(). If the container is const, the loop variable will be const as well.
  5. Legacy Code: In older C++ code, you might encounter begin().const_iterator instead of cbegin(). The cbegin() member function was introduced in C++11 and provides a more concise and readable way to obtain a const_iterator.

These additional points further reinforce the importance of understanding and using const_iterators correctly in C++ code.

One thought on “begin(), vs cbegin(). What’s the difference?”

Leave a Reply

Your email address will not be published. Required fields are marked *