The main benefit is that a std::array
is a first-class object in C++, which means you can do all the things with it that you can do with any other "normal" C++ object.
A traditional C array, on the other hand, is not a first-class object, which means a lot of things won't work:
#include <array>
// Works!
std::array<int, 5> ReturnAStdArrayOfSixes()
{
std::array<int, 5> ret;
ret.fill(6);
return ret;
}
// Doesn't compile, sorry
int[5] ReturnACArrayOfSixes()
{
int ret[5];
for (int i=0; i<5; i++) ret[i] = 6;
return ret;
}
int main(int, char **)
{
std::array<int, 5> stdArray1;
std::array<int, 5> stdArray2;
int cArray1[5];
int cArray2[5];
stdArray1 = stdArray2; // works
cArray1 = cArray2; // error: array type 'int [5]' is not assignable
if (stdArray1 < stdArray2) {/* do something */} // compares arrays' contents lexographically
if (cArray1 < cArray2) {/* do something */} // compiles, but compares pointers which probably isn't what you wanted
return 0;
}
As for "implicit type cast of traditional C array" (by which I think you mean the implicit decay of an array-type into a pointer-type), that's a useful mechanism but it can bite you if you aren't expecting it, e.g.:
// This code works as expected
int myArray[5];
cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";
Now let's refactor the above code into a nice function so we can re-use it:
void PrintArraySize(int myArray[5])
{
std::cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";
}
int main(int, char **)
{
int myArray[5];
PrintArraySize(myArray);
return 0;
}
... Oh noes! Now PrintArraySize() is buggy, and prints a number much smaller than the number of items in the array! (The reason is that myArray
in the function has implicitly decayed to a pointer, so sizeof(myArray)
in the function evaluates to the sizeof(int *)
, e.g. 4 or 8 bytes, rather than the size of the contents of the passed-in array)