Shadow
Shadow

Reputation: 4016

Difference between vector::begin() and std::begin()

While iterating over a vector in c++, I noticed there is a begin() function in the standard library, and also a begin() as a member function of the vector class. What, if any, is the difference between the two, and which should be used over the other?

Example:

vector<int> numbers;
//Code to put values in my vector
for (vector<int>::iterator i = numbers.begin(); i < numbers.end(); i++)
    cout << *i << '\n';

vs:

vector<int> numbers;
//Code to put values in my vector
for (vector<int>::iterator i = std::begin(numbers); i < std::end(numbers); i++)
    cout << *i << '\n';

Upvotes: 60

Views: 15683

Answers (3)

ThatHugo354
ThatHugo354

Reputation: 43

If your compiler optimises your code, it doesn't matter which one you use. Otherwise, you might want to use the more OOP-looking format: numbers.begin()

This code has been plugged into Quick Bench for speed measurement:

std::vector<int> arr = {0,1,2};

static void formatA(benchmark::State& state) {
  for (auto _ : state) { // Code inside this loop is measured repeatedly
    std::vector<int>::iterator itrA = arr.begin(); // arr.end();
    benchmark::DoNotOptimize(itrA);
  }
}
// Register the function as a benchmark
BENCHMARK(formatA);

static void formatB(benchmark::State& state) {
  for (auto _ : state) { // Code before the loop is not measured
    std::vector<int>::iterator itrB = begin(arr); // end(arr);
    benchmark::DoNotOptimize(itrB);
  }
}
BENCHMARK(formatB);

All compiled using STL=libstdc++ (GNU), results for begin() are as follows:

params \ cpu_time (4dp) formatA formatB Conclusion
optim = none
compiler = Clang 11.0
std = c++11
2.1914 5.1870 A is 2.4 times faster than B
optim = none
compiler = Clang 15.0
std = c++20
2.0666 2.8974 A is 1.4 times faster than B
optim = O3
compiler = Clang 11.0
std = c++11
1.1094 1.0130 roughly equivalent runtime
(equivalent assembly)
optim = O3
compiler = Clang 15.0
std = c++20
1.0093 1.0007 roughly equivalent runtime
(equivalent assembly)

Whereas for end():

params \ cpu_time (4dp) formatA formatB Conclusion
optim = none
compiler = Clang 11.0
std = c++11
2.5166 2.6341 roughly equivalent runtime
optim = none
compiler = Clang 15.0
std = c++20
2.3657 3.8461 A is 1.6 times faster than B
optim = O3
compiler = Clang 11.0
std = c++11
1.0045 1.0126 roughly equivalent runtime
(equivalent assembly)
optim = O3
compiler = Clang 15.0
std = c++20
1.0047 1.0012 roughly equivalent runtime
(equivalent assembly)

Without optimisation,
formatA callqs <std::vector<int, std::allocator<int> >::begin()> and end() respectively, while
formatB callqs <decltype (({parm#1}.begin)()) std::begin<std::vector<int, std::allocator<int> > >(std::vector<int, std::allocator<int> >&)> and end() respectively also. Time will be lost by deducing data type for formatB.

WITH optimisation, the compiler has already done the deducing, both will be using the following assembly and varies nothing else other than addresses:

mov    0x3c5b1(%rip),%rax        # 24f188 <arr>
mov    %rax,0x8(%rsp)
add    $0xffffffffffffffff,%rbx

Upvotes: 0

Toby Speight
Toby Speight

Reputation: 30876

The implementation of std::begin() for vectors simply calls std::vector<T>::begin(), so there is no difference between the two in this exact case.

Where std::begin() comes into its own is in generic algorithms:

template<typename Container>
void my_algorithm(Container c) {
    using std::begin;
    using std::end;
    auto const start = begin(c);  // ADL will find the appropriate overload
    auto const finish = end(c);
    // ... rest of code ...
}

Upvotes: 7

John Zwinck
John Zwinck

Reputation: 249384

std::begin() was added in C++11 to make it easier to write generic code (e.g. in templates). The most obvious reason for it is that plain C-style arrays do not have methods, hence no .begin(). So you can use std::begin() with C-style arrays, as well as STL-style containers having their own begin() and end().

If you're writing code which is not a template, you can ignore std::begin(); your fellow programmers would probably find it odd if you suddenly started using it everywhere just because it's new.

Upvotes: 62

Related Questions