35

I have seen in a few places the recommendation to use std::array over C-style arrays in C++, claiming it is a better, safer alternative with no overhead. See:

The standard container array [...] has no space overheads beyond what it needs to hold its elements, [...]. In other words, it is very much like a built-in array without the problems. (C++11 FAQ)

However, as I understand it, being a template container there will be an overhead as far as program size goes, since it will generate code for every different N an array is instanced with.

Suppose my program uses std::array in various places with several different integers for N, will this lead to bloated code? Is it negligible?

Should I worry about this for non-type template parameters in general?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
frangio
  • 855
  • 7
  • 18
  • 2
    there isn't much code in `std::array` which should all be inlined. I can't see how it can increase executable size much. – Bryan Chen Jul 29 '14 at 06:07
  • Can you post some code which produces a bigger executable when you used `std::array` ? – M.M Jul 29 '14 at 06:09
  • 9
    "It" won't generate *anything* besides the storage you request unless you also request the usage of algorithms/members it provides. Which is somewhat the point; *it* provides them so you don't have to. You could certainly use it as a flat array (which is exactly what it is anyway), though I'm pressed to see why you would choose to retool all the wheels it already provides to you. And as template-based offerings go, what you don't use, you don't bloat, so I'm pressed to see where the *down*-side is. – WhozCraig Jul 29 '14 at 06:11
  • 6
    Measure, measure, measure. – Matthieu M. Jul 29 '14 at 08:19

1 Answers1

46

I wouldn't worry about it. If you look at the interface of std::array<T, N>, it is very small and most member functions (basically providing wrappers for pointer manipulation) are one-liners that will be completely optimized away / inlined by any decent compiler on Release mode optimization levels.

Furthermore, you don't pay for what you don't use since unused non-virtual member functions (std::array<T, N> does not have virtual member functions) of class templates are guaranteed not to be instantiated. Small Standard quote:

14.7.1 Implicit instantiation [temp.inst]

11 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation. [...]

There are also some overloaded relational operators == and < that are semantically equivalent to std::equal and std::lexicographical_compare. In practice, these operators should also be implemented in terms of these algorithms (complain to your vendor if they don't).

The only very small worry is a little extra compile-time overhead, but there should be zero code-size and run-time overhead.

Related but not identical: the Technical Report on C++ Performance did a lot of careful benchmarks on thin class wrappers around builtin types (int, double) and found close to zero overhead for 2006 compiler technology. You could repeat their testing to verify this for std::array<T,N> vs. T[N]

Community
  • 1
  • 1
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • 2
    Nice answer ! I always had same doubt as OP's for `std::array`. Also thanks for the link. – P0W Jul 29 '14 at 06:30
  • Re: the last sentence, don't bother. I tried that in 1999, and even 15 years ago there was no measurable difference. – MSalters Jul 29 '14 at 08:11
  • 3
    @MSalters tnx, agreed in principle, but there is no substitute for measuring (it's quite instructive to set up the tests from the quoted report, just to get a feel for how to conduct a proper benchmark) :-) – TemplateRex Jul 29 '14 at 08:12