-2

I have always thought that c arrays would be faster than std::array in C++ but I have done some benchmarking based off the accessing speeds and it appears that the std::array is faster. Why is that?

user1496542
  • 539
  • 2
  • 6
  • 14
  • 1
    @R.MartinhoFernandes Not necessarily. An `std::array` can, for example, provide bounds checking. So can a C style array, for that matter, but it's a lot more difficult, and considerably less likely. – James Kanze Jan 29 '13 at 13:47
  • Perhaps to reverse the negative votes, you might want to post what those benchmark tests were. You've made the question a bit vague. What were the circumstances that the std:array was faster? – Brett McCann Jan 29 '13 at 13:53
  • @JamesKanze this reference site http://en.cppreference.com/w/cpp/container/array/operator_at states that `array::operator[]` does not do any bounds checking. Do you have a quote in the Standard that says it can? – TemplateRex Jan 29 '13 at 13:56
  • 1
    @rhalbersma: think debug builds, where the implementation may choose to `assert(index < size())`. It's undefined to access the indices past the array anyway, so the implementation is free to do whatever it wants if you violate this. –  Jan 29 '13 at 14:05
  • @rhalbersma: The same for std::vector - "Returns a reference to the element at specified location pos. No bounds checking is performed." (http://en.cppreference.com/w/cpp/container/vector/operator_at) They are sequence containers. – SChepurin Jan 29 '13 at 14:27
  • 2
    `std::array` holds a regular C array internally. While it should be quite easy for the compiler to yield the same performance as that of the underlying type (inlining functions) I very much doubt that the performance can be better than the underlying type. – David Rodríguez - dribeas Jan 29 '13 at 14:46
  • @rhalbersma There is a requirement that the index to the `[]` operator be in bounds. The standard doesn't say what happens if it isn't, so it is undefined behavior. Undefined behavior means that the implementation can do anything, including bounds checking. (MS does bounds checking, for example, if the correct options have been selected.) – James Kanze Jan 29 '13 at 16:10
  • @DavidRodríguez-dribeas There are going to be a lot of pointers, and pointer arithmetic, when dealing with C style arrays. If you pass a C style array to a function, the compiler must take possible aliasing of the pointer into account. If you pass a reference to an `std::array`, all of the pointer arithmetic takes place in `std::array`, and the compiler can see where the pointer comes from, and may be able to deduce that there is no aliasing. (May, because of course, if you've takeng the address of the first element, there _is_ aliasing.) – James Kanze Jan 29 '13 at 16:15
  • And FWIW: the "No bounds checking is performed" is only in the imagination of the author of the site you quote. It's certainly not in the standard, and most implementations today _do_ do bounds checking, at least in debug mode. (The correct formulation would be "No bounds checking is required.") – James Kanze Jan 29 '13 at 16:18
  • @JamesKanze: Fair point, to some extent :) The comparison you are doing is between an `std::array` and a pointer obtained from a regular C array. If you pass the array by reference to a function the compiler has exactly the same information in both cases. That is, *after* the array decays into a pointer there is more information in the case of `std::array`, but while the array is seen as an array I cannot think of any optimization that can be taken in one and not the other. – David Rodríguez - dribeas Jan 29 '13 at 16:29
  • @DavidRodríguez-dribeas Since it's a standard class, the compiler could recognize the include, and turn on special optimizations just for it. Or it could be implemented using some special compiler built-ins. (Not that I think that's the case, here or with any other compiler.) – James Kanze Jan 29 '13 at 16:34

1 Answers1

5

The answer is "it depends", or perhaps better put as "nobody knows", as this type of question is always tightly coupled with compiler optimisations, processor architecture and many other factors.

I would also like to point out that if you find one better on one system, it may not reflect that it's better in a diffferent situation - e.g. different compiler or different processor or different operating system. If the overall solution is very similar [and I believe they are in this case], the results of small differences in code generation, or differences in processor architecture can alter the results in either direction. Or for example how well memory allocations line up with cache-lines or virtual memory pages to avoid "extra work".

ALWAYS when discussing performance, never guess and don't ask on the internet. Measure all the options, measure all options again (on some other platform, different compiler options, etc), and then decide which is better [assuming the code is at all performance critical in first place].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227