6

Between std::vector and std::array in TR1 and C++11, there are safe alternatives for both dynamic and fixed-size arrays which know their own length and don't exhibit horrible pointer/array duality.

So my question is, are there any circumstances in C++ when C arrays must be used (other than calling C library code), or is it reasonable to "ban" them altogether?

EDIT:

Thanks for the responses everybody, but it turns out this question is a duplicate of

Now that we have std::array what uses are left for C-style arrays?

so I'll direct everybody to look there instead.

[I'm not sure how to close my own question, but if a moderator (or a few more people with votes) wander past, please feel free to mark this as a dup and delete this sentence.]

Community
  • 1
  • 1
Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82
  • Check this:-http://stackoverflow.com/questions/4424579/stdvector-versus-stdarray-in-c – ravi Oct 12 '14 at 16:18
  • Currently, simply including `` of libstdc++ includes about 16,000 lines of code. If you need to reduce that, you'd probably have to write your own `std::array`, for which you'll need C-style arrays. – dyp Oct 12 '14 at 16:46
  • 1
    Non of the 3 types are perfect for all needs. So select for your needs. `std::vector` is never a replacement for a c-style array or `std::array` because it includes a lot of things like dynamic allocation and others which needs more memory and time. So we only accept std::vector in dynamic situations. Both others are nearly equivalent. And yes std::array is only a wrapper over c-style array! Most problems with arrays are the same like out of bounds access. – Klaus Oct 12 '14 at 16:47
  • possible duplicate of [Now that we have std::array what uses are left for C-style arrays?](http://stackoverflow.com/questions/6111565/now-that-we-have-stdarray-what-uses-are-left-for-c-style-arrays) – Tristan Brindle Oct 14 '14 at 16:17

7 Answers7

5

I didnt want to answer this at first, but Im already getting worried that this question is going to be swamped with C programmers, or people who write C++ as object oriented C.

The real answer is that in idiomatic C++ there is almost never ever a reason to use a C style array. Even when using a C style code base, I usually use vectors. How is that possible, you say? Well, if you have a vector v and a C style function requires a pointer to be passed in, you can pass &v[0] (or better yet, v.data() which is the same thing).

Even for performance, its very rare that you can make a case for a C style array. A std::vector does involve a double indirection but I believe this is generally optimized away. If you dont trust the compiler (which is almost always a terrible move), then you can always use the same technique as above with v.data() to grab a pointer for your tight loop. For std::array, I believe the wrapper is even thinner.

You should only use one if you are an awesome programmer and you know exactly why you are doing it, or if an awesome programmer looks at your problem and tells you to. If you arent awesome and you are using C style arrays, the chances are high (but not 100%) that you are making a mistake,

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72
  • 1
    On a platform with limited memory, C-style arrays allow for known usage of memory. There would be no fragmentation. – Thomas Matthews Oct 12 '14 at 18:13
  • In most implementations, the fill constructor and reserve only allocate exactly as much memory as they need. Other than that, an array just uses sixteen extra bytes on the stack and that's it. I'm not sure what you mean by no fragmentation, vectors are guaranteed to have contiguous storage. Can you explain? If your memory is so limited that any of these things matter, I find it unlikely you're using c++ instead of c. Vtables, templates, etc: all these abstractions have finite cost. – Nir Friedman Oct 12 '14 at 20:41
2
Foo data[] = {

is a pretty common pattern. Elements can be added to it easily, and the size of the data array grows based on the elements added.

With C++11 you can replicate this with a std::array:

template<class T, class... Args>
auto make_array( Args&&... args )
-> std::array< T, sizeof...(Args) >
{
  return { std::forward<Args>(args)... };
}

but even this isn't as good as one might like, as it does not support nested brackets like a C array does.

Suppose Foo was struct Foo { int x; double y; };. Then with C style arrays we can:

Foo arr[] = {
  {1,2.2},
  {3,4.5},
};

meanwhile

auto arr = make_array<Foo>(
  {1,2.2},
  {3,4.5}
};

does not compile. You'd have to repeat Foo for each line:

auto arr = make_array<Foo>(
  Foo{1,2.2},
  Foo{3,4.5}
};

which is copy-paste noise that can get in the way of the code being expressive.

Finally, note that "hello" is a const array of size 6. Code needs to know how to consume C-style arrays.

My typical response to this situation is to convert C-style arrays and C++ std::arrays into array_views, a range that consists of two pointers, and operate on them. This means I do not care if I was fed an array based on C or C++ syntax: I just care I was fed a packed sequence of data elements. These can also consume std::dynarrays and std::vectors with little work.

It did require writing an array_view, or stealing one from boost, or waiting for it to be added to the standard.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • *"Code needs to know how to consume C-style arrays."* There is the `s` suffix in C++14, but AFAIK, it's impossible to write a user-defined literal suffix that produces a `std::array` (of a size determined by the length of the string). :( – dyp Oct 12 '14 at 16:50
  • *"but even this isn't as good as one might like"* Also, it needs to copy/move the elements (no $ elision, needs $able types). – dyp Oct 12 '14 at 16:52
  • @dyp *nod*, and free store allocated arrays (like `""s") is not a replacement for automatic storage arrays (like `""`). If we where able to manipulate braced-init-lists as programmers we could get further. – Yakk - Adam Nevraumont Oct 12 '14 at 16:59
0

Sometimes an exsisting code base can force you to use them

Liam Clark
  • 106
  • 1
  • 2
  • 8
0

The last time I needed to use them in new code was when I was doing embedded work and the standard library just didn't have an implementation of std::vector or std::array. In some older code bases you have to use arrays because of design decisions made by the previous developers.

In most cases if you are starting a new project with C++11 the old C style arrays are a fairly poor choice. This is because relative to std::array they are difficult to get correct and this difficulty is a direct expense when developing. This C++ FAQ entry sums up my thoughts on the matter fairly well: http://www.parashift.com/c++-faq/arrays-are-evil.html

shuttle87
  • 15,466
  • 11
  • 77
  • 106
0

Pre-C++14: In some (rare) cases, the missing initialization of types like int can improve the execution speed notably. Especially if some algorithm needs many short-lived arrays during his execution and the machine has not enough memory for pre-allocating making sense and/or the sizes could not be known first

deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • 1
    `std::array arr;` does not initialize the stored integers. For `std::vector`, you can write a custom allocator that does not initialize the elements (default-initializes). – dyp Oct 12 '14 at 16:36
  • Variable-sized stdarray? And about the vector...well, possible. – deviantfan Oct 12 '14 at 16:41
  • 1
    As I said in a comment to M M.'s answer, VLAs are (though a compiler extension in C++) a valid reason to not use `std::array` currently. There are proposals for variable-sized wrapped arrays such as `std::dynarray`, but nothing standardized yet. – dyp Oct 12 '14 at 16:43
0

C-style arrays are very useful in embedded system where memory is constrained (and severely limited).

The arrays allow for programming without dynamic memory allocation. Dynamic memory allocation generates fragmented memory and at some point in run-time, the memory has to be defragmented. In safety critical systems, defragmentation cannot occur during the periods that have critical timing.

The const arrays allow for data to be put into Read Only Memory or Flash memory, out of the precious RAM area. The data can be directly accessed and does not require any additional initialization time, as with std::vector or std::array.

The C-style array is a convenient tool to place raw data into a program. For example, bitmap data for images or fonts. In smaller embedded systems with no hard drives or flash drives, the data must directly accessed. C-style arrays allow for this.

Edit 1:
Also, std::array cannot be used with compiler that don't support C++11 or afterwards.

Many companies do not want to switch compilers once a project has started. Also, they may need to keep the compiler version around for maintenance fixes, and when Agencies require the company to reproduce an issue with a specified software version of the product.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • So, why use C-style arrays instead of `std::array`? – dyp Oct 12 '14 at 18:28
  • *"Also, std::array cannot be used with compiler that don't support C++11 or afterwards."* `std::array` has been in TR1, which only uses C++03 features. You can also write your own in C++03. – dyp Oct 12 '14 at 18:57
0

I found just one reason today : when you want to know preciselly the size of the data block and control it for aligning in a giant data block . This is usefull when your are dealing with stream processors or Streaming extensions like AVX or SSE. Control the data block allocation to a huge single aligned block in memory is usefull. Your objects can manipulate the segments they are responsible and, when they finished , you can move and/or process the huge vector in an aligned way .

ivan
  • 1