2

What (if anything) can be done more efficiently with a array rather than a container?

I recently learned about C++ standard container classes. They have clear advantages and solve common problems with C-style arrays. The FAQs list on "why arrays are evil" can be summarized loosely like this:

1. subscripts are not checked
2. often it is required to allocate memory from the heap
3. not easy to insert elements in the middle
4. always passed as reference

I guess there are many cases, where one can live with these disadvantages. However, I am a bit puzzled about the question, what is it that can be done more efficient / easier with arrays rather than with containers? Or is there actually nothing like that and I really should not care about arrays anymore?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Please review their page on [what "evil" means](http://www.parashift.com/c++-faq/defn-evil.html). TL;DR don't take it too seriously. (It would be dishonest to suggest that the FAQ is telling you to never use arrays again.) –  Dec 16 '14 at 20:15
  • Given C++11, there's `std::array` which AFAIK completely supersedes C-style arrays. They are needed to implement `std::array`, and can't be removed because that would massively break compatibility, but if you're writing C++11, there really is no reason to use arrays. Of course, the FAQ most likely predates C++11 so this is a good question for C++98. –  Dec 16 '14 at 20:20
  • @remyabel yes you are right, I will edit. Actually I was considering not to mention any reference to the faq (and the "evil"-buissness) as it is misunderstood and critized already often enough – 463035818_is_not_an_ai Dec 16 '14 at 20:25
  • 2
    C-style arrays allows to have so many question on SO... – Jarod42 Dec 16 '14 at 20:26
  • Plain old arrays might be the right thing, if you have a predefined data structure (which can be a sorted/unsorted array or even representing a map) - I actually use std::lower_bound on these predefined values. It is up to you to choose the right tool (c-array, maybe a goto, maybe ...) –  Dec 16 '14 at 20:28
  • Well standard containers' subscript operator `[]` are not bound-checked either. Only `at` function is checked. And arrays are not passed by reference. They can be passed as reference, or value (which will decay to pointer) – SwiftMango Dec 16 '14 at 20:49

5 Answers5

6

"However, I am a bit puzzled about the question, what is it that can be done more efficient / easier with arrays rather than with containers?"

Well, if you're referring to c-style arrays, with the current c++ standard, there's nothing left about the disadvantages of the classic standard c++ container classes (like e.g. std::vector) IMHO. These have a dependency to have allocatable memory (with new()), and that could well be be a restriction for your current (OS/bare metal) environment, as not being available out of the box.


The current standard provides std::array, that works without dynamic memory allocation needs, but fulfills all of the claims:

"1. subscripts are not checked"

std::array does subscript checking

"2. often it is required to allocate memory from the heap"

It's the client's choice where it's actually allocated with std::array. std::vector suffices anyway for doing this.

"3. not easy to insert elements in the middle"

Well, that's one point not supported well by std::array out of the box. But again, std::vector and other container classes support this well (as long your environment supports dynamic memory allocation)

"4. always passed as reference"

std::array supports passing by reference well, and much better than it can (can't) be achieved with c-style arrays.


Though there may be specialized cases for e.g. reusable object instance pools, or flyweight object instances, you might want to solve using the placement new() operator. Implementations for such solutions, usually would involve you're going to operate on raw c-style arrays.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    Actually, there _is_ a nit where built-in arrays have an advantage over all alternatives: you can create a built-in array on the stack with a size matching its list of initializers. Not big but actually important... – Dietmar Kühl Dec 16 '14 at 20:36
  • Maybe it's because I'm tired but I can barely make heads or tails of that first paragraph. Could you maybe rephrase it? – Lightness Races in Orbit Dec 16 '14 at 20:41
  • This answer gets at the heart of the issue. The biggest difference with vectors is their reliance on the heap. For cases where you know the capacity at compile time but still want most of the features/protection of vector std::array is the way to go. **Unless** you are interfacing with c-style arrays and you don't want to copy the data over. In that case you're only choice would be reinterpret_cast which is just not a good idea. http://stackoverflow.com/questions/11205186/treat-c-cstyle-array-as-stdarray – cmaynard Dec 16 '14 at 20:44
  • @LightnessRacesinOrbit Sorry I'm german, we tend to write nested sentences instead of shorter separate statement. Tried to improve my essences. – πάντα ῥεῖ Dec 16 '14 at 20:47
  • @πάνταῥεῖ Your apology for being German is accepted ;) Anyway it's still not reading clearly to me, perhaps because you in fact didn't change any of the words... Oh well. – Lightness Races in Orbit Dec 16 '14 at 20:52
  • @LightnessRacesinOrbit /OT _"Your apology for being German is accepted"_ Looks like we have to apologize a lot for our fellow citizens' weird behavior (PEGIDA and such), and I'd never stop to do so, and to point out I'm not one of these idiots. Though my apology, only was for the grammatical style differences of our languages ;-) ... (If you at least got my point, you're well invited to improve my wording) – πάντα ῥεῖ Dec 16 '14 at 20:56
  • Oh, this is _much_ better now. Still some funny words here and there but I can at least understand what you're saying ;) Thanks – Lightness Races in Orbit Dec 16 '14 at 21:26
4

Built-in arrays are a low-level tool with a somewhat awkward interface. They are needed to implement better to use classes, though: one of the nice things about C++ is that exposes many of the low-level tools to create efficient implementations of higher-level abstractions. To me, the primary uses of built-in arrays are these:

  1. The mechanism to implement higher-level abstractions like std::vector<T> or std::array<T, N> (well, std::vector<...> and family don't really use built-in arrays but deal diretly with raw memory internally).
  2. When I need an array of values initialized with a sequence of values allocated on stack, I'd use built-in arrays (std::array<...> can't deduce the number of arguments and anything using std::initializer_list<T> to get initialized won't have a fixed size).

Even though std::array<T, N> is really just a rewrite of [some of] the functionality of built-in arrays it has the nice feature that a debug implementation can assert assumptions which are made.

BTW, you list doesn't include on of the bigger issues: if you have a variable sized array, you'll need to give it your element type a default constructor. With C++11 the default constructor can, at least, be defaulted (that is an issue if your class needs another constructor) which can avoid initialization of objects about to be initialized. However, the various container classes take a lot of the complexity out of the picture.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
3

Arrays on the stack can be more efficient than a vector, since the vector will always do a separate memory allocation. You're unlikely to notice the difference unless it's something performed many times in a large tight loop.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • There is also the opposite argument that vectors have little to no overhead over arrays and that vectors should always be preferred. –  Dec 16 '14 at 20:31
  • 3
    True, but C++11 also includes `std::array` which is allocated on the stack like plain arrays. – Nicu Stiurca Dec 16 '14 at 20:31
  • 2
    @remyabel I just gave the example where they *do* have overhead over an array. If those conditions don't apply then feel free to prefer whatever you want. – Mark Ransom Dec 16 '14 at 20:33
1

Or is there actually nothing like that and I really should not care about arrays anymore?

Consider that C++ dates to 1983, and it has seen a number of big changes since then. The container classes that are available now were designed to avoid the pitfalls that you listed, so it's not surprising that they're better in those respects. There is one thing that you can do with C-style arrays that you can't with modern container classes, however: you can compile your code with very old compilers. If you have a pressing need to maintain compatibility with compilers from the mid-1980's, you should stick with C-style arrays. Otherwise, use the newer, better approach.

Caleb
  • 124,013
  • 19
  • 183
  • 272
1

c-stlye arrays have several advantages over stl containers (specifically std::array). Of course the same is true the other way around.

For one, with c-style arrays you have control over memory layout, which is extremely useful when interpreting network packets, or any similar data sources. This allows you to cast a block of memory to a struct, saving copy/assignment operations, which is necessary in some performance sensitive applications.

Another reason is simplicity - in a case where you don't need any of the benefits std containers offer, why use them?

And there's compatibility - different stl implementations will change with different compilers. Using arrays in the interfaces of shared libraries (so/dll) instead of stl containers allows the user to write against the shared library using almost any compiler. This is explicitly not true for stl containers.

Finally there's low level optimizations. There are situations where arrays can be faster than their stl equivalent std::array, although these situations are somewhat rare.

Peter
  • 5,608
  • 1
  • 24
  • 43