11

I've noticed there are 2 ways to get the end iterator of a vector (or other container class):

std::end(myVector)

and

myVector.end()

The same goes for various other container iterator functions, begin, cend, cbegin, rend, rbegin, crend, crbegin, find, etc. What I'm wondering is if there's any functional difference between these? And if not, is there some historical reason to have both of them?

(Apologies if this is a duplicate, I've searched all over, and found plenty of sources for one or the other of these methods, but none that mentions both or compares the two.)

Darrel Hoffman
  • 4,436
  • 6
  • 29
  • 41

1 Answers1

12

There is a historical reason: before C++11, only the member function versions existed. C++11 added the non-members, which also work for plain C-style arrays, so can be considered to be more general.

int a[] = {3, 1, 5, 67, 28, -12};
std::sort(std::begin(a), std::end(a));

When applied to standard library containers, the effect of std::begin and std::end is to call the container's begin() and end() member functions, so there is no functional difference.

C++14 added std::cbegin, std::cend, std::rbegin, std::rend, std::crbegin and std::crend, with similar behaviour.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • So the only difference is the new method also works on arrays? Okay. Useful, I guess - I may have to ask the person who wrote this code why we're using it on `vector`s and just making the code needlessly more verbose, but I guess that answers my question. – Darrel Hoffman Mar 08 '16 at 21:33
  • @DarrelHoffman I guess it is a matter of choice, but I prefer using non-member functions if possible. BTW if the parameter is a standard library container, the `std::` can be omitted, and `begin(v)` isn't much more verbose than `v.begin()`. – juanchopanza Mar 08 '16 at 21:36
  • Yes, though potentially dangerous in this case - Much of our codebase is shared by many teams in different parts of the world, some of whom are still running C++0x for legacy reasons. I don't expect this particular part of the code to cause problems, but there've been conflicts in the past over that. (We have to mark certain classes as "No C++11 allowed" so that it doesn't break other teams' builds...) – Darrel Hoffman Mar 08 '16 at 21:44
  • 1
    @DarrelHoffman: note that although `std::begin`, `std::end` (etc.) were only added to the standard in C++11 (and 14), they can be implemented using only features available in C++98, so if you want to use free functions and retain compatibility with older compilers, that's entirely possible. – Jerry Coffin Mar 08 '16 at 22:01
  • I like v1.insert(begin(v2), end(v2)); more than v1.insert(v2.begin(), v2.end()). It seems cleaner and leverages ADL to drop "std::" prefix. It's shorter by 2 characters as well :) Of course, due to ADL, it doesn't work with raw arrays. You'd have to provide the std:: prefix then. Taking advantage of ADL is cool and not many people use that, e.g.: find(begin(v), end(v), value); is much cleaner without "std::" – reconn Apr 13 '20 at 10:24