简体   繁体   中英

Is there ever a valid reason to use C-style arrays in C++?

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.]

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,

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; }; 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::array s into array_view s, 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::dynarray s and std::vector s 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.

有时,现有的代码库会强制您使用它们

Technically, you can rewrite C-style arrays with std::array or std::vector based on your usage.

However, std::array itself uses C-style arrays. std::array is declared by C-style arrays under the hood. Therefore, the existence of this array is somehow essential if we want avoid compiler magics.

template <class T, int N>
class Array
{
    T data[N];
    .
    .

Sometimes writing a small code, I prefer old-school arrays rather than those classes. And if you OK with compiler extensions, you can take advantages of variable length nature of C-style arrays in your code. (Simplicity)

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

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

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM