Aayush Mahajan
Aayush Mahajan

Reputation: 4033

Why does .at() member function of a vector return a reference instead of an iterator?

Up until a few days ago I thought all 'position' related member functions of a vector returned an iterator. I found out recently that while insert() and erase() functions do indeed return iterators, begin() and end() do so by definition, but functions like at(), front(), back() do not do so, they return a simple reference.

While references make life easier as I would not have to dereference the iterator fist, to me it still seems inconsistent that some member functions are returning a reference instead of an iterator. If anything, C++ tries to minimize inconsistencies like this by providing the bare minimum while still maintaining ease in programming.

Upvotes: 0

Views: 331

Answers (3)

Pete Becker
Pete Becker

Reputation: 76523

The abstraction that the Standard Template Library presents is sequences, iterators, and algorithms. Container are one way of creating and managing sequences, but they are not the only way. For example, an input stream can be used as a sequence, by creating a std::istream_iterator. But things like int i; double d; std::cin >> i >> d; would be rather awkward to write if std::cin only defined an iterator-based interface. Same thing for containers: they're useful in contexts other than iteration, and they define interfaces appropriate to their general uses; one of those uses is as a sequence for STL algorithms, but there are other uses, too.

Upvotes: 0

Yuki
Yuki

Reputation: 4193

at method is from the group of common container methods called 'Element access', those return reference, pointers. There is another group of common container methods called 'Iterators', those return iterators. It is clear, simple and well-known design decision for the standard library.

Element access

  • at: access specified element with bounds checking
  • operator[]: access specified element
  • front: access the first element
  • back: access the last element
  • data direct access to the underlying array

Iterators

  • begin/cbegin returns an iterator to the beginning
  • end/cend returns an iterator to the end
  • rbegin/crbegin returns a reverse iterator to the beginning
  • rend/crend returns a reverse iterator to the end

In the iterator concept, elements within iterator range are accessed through std::advance method of STD. This would work for InputIterators, for BST, list, vectors, etc., of course with different complexity.

Upvotes: 9

Michael Kenzel
Michael Kenzel

Reputation: 15951

begin(), end(), insert(), erase(), etc. are methods that work on the vectors' sequence of elements itself, while operator [], at(), front(), and back() are methods that access concrete elements of this sequence. I don't really see an inconsistency here. They exist for all sequence containers and they always do conceptually the same thing. Sure, you could implement something like front() and back() yourself, nothing keeps you from doing so. They are by definition equivalent to dereferencing begin() and prev(end()) respectively. They exist for convenience. Depending on how far you want to go, std::vector itself exists just for convenience…

Upvotes: 1

Related Questions