Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::accumulate behave like this with standard arrays?

I'm just getting into C++ and I think I have a handle on pointers, but std::accumulate() has me confused.

Given the array:

int a[3] = { 5, 6, 7 };

I'd like to sum the values of the array with std::accumulate(), so I pass it a pointer to the first element, then the last, then the starting value of the accumulator.

std::accumulate(a, a + 2, 0);
std::accumulate(&a[0], &a[2], 0);

Oops: either of these returns the sum of only the first two elements: 11.

On the other hand, if the second argument is a nonsensical pointer, just out of bounds...

std::accumulate(a, a + 3, 0);
std::accumulate(&a[0], &a[3], 0);

... the correct value of 18 is returned.

Could someone please explain this? I realise that I could avoid using simple arrays, but that's beside the point.

like image 830
Jamie Schembri Avatar asked Jul 31 '14 23:07

Jamie Schembri


People also ask

How does std :: accumulate work?

std::accumulate() is a built-in function in C++'s Standard Template Library. The function takes in a beginning iterator, an ending iterator, initial value, and (by default) computes the sum of the given initial value and the elements in the given range. The function can also​ be used for left folding.

Is std :: accumulate faster?

As I expect, the manually unrolled loop is the fastest one, but more interesting is that std::accumulate is much slower than simple loop.

Is std :: array slower than C array?

The std::array is designed as zero-overhead wrapper for c-style arrays. It will provide a value like semantics equally to the other C++ containers. A std::array should have same runtime performance as a c-style array.

What is the difference between std :: array and array?

std::array is just a class version of the classic C array. That means its size is fixed at compile time and it will be allocated as a single chunk (e.g. taking space on the stack). The advantage it has is slightly better performance because there is no indirection between the object and the arrayed data.


1 Answers

C++ ranges are defined as [first, last), and all the STL algorithm work like that. In this case, std::accumulate sums up all the elements behind the iterator-defined range, starting with first and ending at last without actually dereferencing it.

Thus, calling it like std::accumulate(a, a+3, 0) is actually correct and equal to calling it with std::accumulate(begin(a), end(a), 0).

Also note that this doesn't fall foul of the "no pointers to outside of allocated arrays" rule, as there is a specific exception for pointer to just behind the last element.

like image 170
Xarn Avatar answered Nov 15 '22 17:11

Xarn