4

Popular opinion is that C++ array is safer with almost equal efficiency. Except for checking whether the index is out of range and not allowing implicit type cast to pointer, are there any other features?

Besides, why implicit type cast of traditional C array is regarded as a bad way?

I'm not very good at C++(also at English),plz forgive me if this question is not worth an answer. Thank you!

o_oTurtle
  • 1,091
  • 3
  • 12
  • C arrays decay nearly instantly into pointers the moment you try to do anything useful with them, and once you get a pointer you have no clean way to get the size of the container. – Etienne de Martel Apr 17 '21 at 01:57
  • 1
    The `std::array` is just as efficient as a *built-in* array. Its features come free of cost. – Galik Apr 17 '21 at 02:25
  • `std::array` can be treated as a values, they can be copied, passed as arguments, reasoning becomes easier, can be put in containers, etc. – alfC Apr 18 '21 at 02:42

2 Answers2

8

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)

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
0

Not sure what you exactly meant by your question about the implicit cast of a C array, but I'm guessing you meant either casting implicitly the values stored inside (like in int a[10]; float f=a[0]), or casting the implicit pointer to the first element (like in int a[10]; void* p=a;). Anyway, casting any pointer to void* pointer implicitly is ok (you just need to know what is the size of the memory stored at such pointer if you want to read it), because void* pointers aren't really meant for data manipulation, so whenever you use a void* pointer, you know what you are doing, right?

But a bit more seriously now - implicit casting, in general, is something that the compiler does according to the language rules, without asking the programmer if it is what was actually desired. That's why it sometimes can lead to errors in the code (programmer's oversight, or incorrect assumptions as to what is happening during such a cast).

When you cast explicitly, then, first of all, you make sure that you get the desired result. But what is more important, if your explicit cast gives ambiguous result for the compiler, or even it turns out impossible to the compiler, then the compiler will inform you about that, and you will be able to revise your casting decisions early and prevent bugs in your code.

So explicit casting is just a way to talk to the compiler more strictly, making sure that it understands better what you meant when you wrote your code. Then, in return, the compiler gives you hints when you cast something incorrectly (with implicit casting it would do things its own way, and you wouldn't even know when the effect of such a cast was different than you wanted).

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tomek
  • 353
  • 2
  • 7