Now that we have std::array what uses are left for C-style arrays?
C++ArraysC++11InitializationC++ 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:
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++
- to implement something like
std::array
- if you don't want to use the STL or can't
- For performance