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

C++ArraysC++11Initialization

C++ Problem Overview


std::array is vastly superior to the C arrays. And even if I want to interoperate with legacy code, I can just use std::array::data(). Is there any reason I would ever want an old-school array?

C++ Solutions


Solution 1 - C++

Unless I've missed something (I've not followed the most recent changes in the standard too closely), most of the uses of C style arrays still remain. std::array does allow static initialization, but it still won't count the initializers for you. And since the only real use of C style arrays before std::array was for statically initialized tables along the lines of:

MyStruct const table[] =
{
	{ something1, otherthing1 },
	//  ...
};

using the usual begin and end template functions (adopted in C++11) to iterate over them. Without ever mentionning the size, which the compiler determines from the number of initializers.

EDIT: Another thing I forgot: string literals are still C style arrays; i.e. with type char[]. I don't think that anyone would exclude using string literals just because we have std::array.

Solution 2 - C++

No. To, uh, put it bluntly. And in 30 characters.

Of course, you need C arrays to implement std::array, but that's not really a reason that a user would ever want C arrays. In addition, no, std::array is not less performant than a C array, and has an option for a bounds-checked access. And finally, it is completely reasonable for any C++ program to depend on the Standard library- that's kind of the point of it being Standard- and if you don't have access to a Standard library, then your compiler is non-conformant and the question is tagged "C++", not "C++ and those not-C++ things that miss out half the specification because they felt it inappropriate.".

Solution 3 - C++

Seems like using multi-dimensional arrays is easier with C arrays than std::array. For instance,

char c_arr[5][6][7];

as opposed to

std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;

Also due to the automatic decay property of C arrays, c_arr[i] in the above example will decay to a pointer and you just need to pass the remaining dimensions as two more parameters. My point is it c_arr is not expensive to copy. However, cpp_arr[i] will be very costly to copy.

Solution 4 - C++

As Sumant said, multi-dimensional arrays are a lot easier to use with built in C-arrays than with std::array.

When nested, std::array can become very hard to read and unnecessarily verbose.

For example:

std::array<std::array<int, 3>, 3> arr1; 

compared to

char c_arr[3][3]; 

Also, note that begin(), end() and size() all return meaningless values when you nest std::array.

For these reasons I've created my own fixed size multidimensional array containers, array_2d and array_3d. They are analogous to std::array but for multidimensional arrays of 2 and 3 dimensions. They are safer and have no worse performance than built-in multidimensional arrays. I didn't include a container for multidimensional arrays with dimensions greater than 3 as they are uncommon. In C++0x a variadic template version could be made which supports an arbitrary number of dimensions.

An example of the two-dimensional variant:

//Create an array 3 x 5 (Notice the extra pair of braces) 

fsma::array_2d <double, 3, 5> my2darr = {{
    { 32.19, 47.29, 31.99, 19.11, 11.19},
    { 11.29, 22.49, 33.47, 17.29, 5.01 },
    { 41.97, 22.09, 9.76, 22.55, 6.22 }
}};

Full documentation is available here:

http://fsma.googlecode.com/files/fsma.html

You can download the library here:

http://fsma.googlecode.com/files/fsma.zip

Solution 5 - C++

The C-style arrays that are available in C++ are actually much less versatile than the real C-arrays. The difference is, that in C, array types can have runtime sizes. The following is valid C code, but it can neither be expressed with C++ C-style arrays nor with the C++ array<> types:

void foo(int bar) {
    double tempArray[bar];
    //Do something with the bar elements in tempArray.
}

In C++, you would have to allocate the temporary array on the heap:

void foo(int bar) {
    double* tempArray = new double[bar];
    //Do something with the bar elements behind tempArray.
    delete[] tempArray;
}

This cannot be achieved with std::array<>, because bar is not known at compile time, it requires the use of either C-style arrays in C++ or of std::vector<>.


While the first example could relatively easily be expressed in C++ (albeit requiring new[] and delete[]), the following cannot be achieved in C++ without std::vector<>:

void smoothImage(int width, int height, int (*pixels)[width]) {
    int (*copy)[width] = malloc(height*sizeof(*copy));
    memcpy(copy, pixels, height*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y][x] = //compute smoothed value based on data around copy[y][x]
        }
    }
    free(copy);
}

The point is, that the pointers to the line arrays int (*)[width] cannot use a runtime width in C++, which makes any image manipulation code much more complicated in C++ than it is in C. A typical C++ implementation of the image manipulation example would look like this:

void smoothImage(int width, int height, int* pixels) {
    int* copy = new int[height*width];
    memcpy(copy, pixels, height*width*sizeof(*copy));
    for(y = height; y--; ) {
        for(x = width; x--; ) {
            pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
        }
    }
    delete[] copy;
}

This code does precisely the same calculations as the C code above, but it needs to perform the index computation by hand wherever the indices are used. For the 2D case, this is still feasible (even though it comes with a lot of opportunities to get the index calculation wrong). It gets really nasty in the 3D case, though.

I like writing code in C++. But whenever I need to manipulate multidimensional data, I really ask myself whether I should move that part of the code to C.

Solution 6 - C++

May be the std::array is not slow. But I did some benchmarking using simple store and read from the std::array; See the below benchmark results (on W8.1, VS2013 Update 4):

ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;

test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305

According to the negative marks, the code I used is in the pastebin (link)

The benchmark class code is here;

I don't know a lot about benchmarkings... My code may be flawed

Solution 7 - C++

  1. to implement something like std::array
  2. if you don't want to use the STL or can't
  3. For performance

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionR. Martinho FernandesView Question on Stackoverflow
Solution 1 - C++James KanzeView Answer on Stackoverflow
Solution 2 - C++PuppyView Answer on Stackoverflow
Solution 3 - C++SumantView Answer on Stackoverflow
Solution 4 - C++Ricky65View Answer on Stackoverflow
Solution 5 - C++cmaster - reinstate monicaView Answer on Stackoverflow
Solution 6 - C++K'PrimeView Answer on Stackoverflow
Solution 7 - C++Lou FrancoView Answer on Stackoverflow