-1

If I have the two following statements:

// OK
const int ARRAYSIZE = 5;
int x[ARRAYSIZE];

// NOT OK
int ARRAYSIZEBAD = 5;
int y[ARRAYSIZEBAD];

And I don't compile with the -pedantic-errors flag... why is the second example a bad thing? In what situation would it be preferable to use dynamic allocation with the new operator?

trincot
  • 317,000
  • 35
  • 244
  • 286
JoeBass
  • 519
  • 7
  • 18
  • 7
    It's not bad per se, it's just not a feature the language offers. The size of things must be known at compile time which means you need a compile time known value for array sizes. – NathanOliver Feb 25 '19 at 17:49
  • " In what situation would it be preferable to use dynamic allocation with the new operator?" this is maybe a completely different question. Related but not the same as the rest of your question – 463035818_is_not_an_ai Feb 25 '19 at 17:53
  • In addition to what NathanOliver said, if you want to dynamically create an array like in the second example, you can use `int* y = new int[ARRAYSIZEBAD];` –  Feb 25 '19 at 17:55
  • @user463035818 it is the same question though. the responses i'm getting is "because the compiler says so", but that's a circular argument. in addition, the GNU compiler doesn't require it unless you used the -pedantic-errors flag. – JoeBass Feb 25 '19 at 17:55
  • 1
    @user463035818 yep this is a dupe of that question... – JoeBass Feb 25 '19 at 18:02
  • 3
    @JoeBass "because the compiler says so" is not very good answer. Better answer is "because the *language* says so". – eerorika Feb 25 '19 at 18:11
  • you dont need to edit your question to point to the duplicate. Once closed as duplicate the question gets a link to the dupe on top of it. – 463035818_is_not_an_ai Feb 25 '19 at 20:07

4 Answers4

6

C++ Why are non-const array declarations bad?

Because the length of the array must be known at the time of compilation. If a variable is non-const, then its value could change at run time, and thus would not be known at compile time. Only a compile time constant expression can be used as the length of an array - thus a const variable can only be used as the length of an array after its initialiser has been observed.

int[ARRAYSIZE] is a type. The requirement that size is known at compile time extends to all types that you instantiate, not just array types.

In what situation would it be preferable to use dynamic allocation ...

You need dynamic allocation when you don't know the length of the array at compile time.

You also need non-automatic allocation when the array is big. This is because the memory reserved for automatic allocation is often quite limited.

... with the new operator?

It's rarely preferable to allocate dynamic memory using a new-expression. std::vector is typically used when dynamic array is needed.

eerorika
  • 232,697
  • 12
  • 197
  • 326
2

As a couple of people of people have pointed out, C++ usually determines array sizes at compile time, not run time.

A variable has its value set at runtime, so there is no way to determine the size at compile time. That is, except for constant variables. Constant variables have a constant value through the entire program, and, thus, can be determined at compile time.

If you need an array that has a dynamic size, you have the option of the new keyword:

int* y = new int[mySize];

Of course, when you're done with it, you should delete it as well.

delete[] y;

Edit: Thanks to @WhozCraig who reminded me/pointed out that you have an even better option than new/delete. You can also use vector as well.

To use, just include <vector>

#include <vector>

and you can use it like this:

std::vector<int> y; // replace int with any type of object you want

This will allow you to dynamically modify the size of your "array" (so to speak) any time you want.

1

The reason it's bad is that it's not valid C++ code. Some C++ compilers will compile it because of support for Variable-Length-Arrays (VLAs), but this is not a core supported C++ language feature and will not work on all Standard-conforming compilers.

In C++, if you know at compile-time the length of an array, you should use std::array<int, 5>, which is a replacement for and strictly better version of the "C-style array", i.e. int arr[5];. If you do not know the length at compile-time, and have to determine it at run-time, you should use std::vector<int>, which is a replacement for int* arr = new int[5];, and which has the added benefit that you don't need to remember to call delete[] later on, as the vector object will make sure the deleter is correctly called if the object goes out of stack.

Xirema
  • 19,889
  • 4
  • 32
  • 68
  • "if you know at compile-time the length of an array, you should use std::array" -- one comment: this is only true if the length is not too large because too large arrays (on the stack) can cause stack overflow. – Handy999 Feb 25 '19 at 21:04
-5

Remember: C and C++ are not Java. Arrays, for instance, are just a pointer to N pieces of memory. They are not Objects where you could store additional information, such as the size of the array. Thus, the compiler needs to know the size.

The reason isn't obvious for vectors. After all, you can use int * instead and then allocate whatever size you want.

But if you have a multi-dimensional array, it becomes more obvious why the compiler must know the size.

int myArray[3][3];

This is still just 9 ints of memory stored in the order of [0][0], [0][1], [0][2], [1][0] etc. So to get to myArray[2][1], the compiler knows to go to the 8th integer.

But here's a little more info on why it matters for 1-D arrays.

int myArray[10];
int myNextArray[5];

In this case, you have two pieces of memory, one that's 10 ints long and one that's 5 ints long. If the compiler doesn't know the size of them, how will it know how much space they each take, so it knows how to set up at the start of your method?

Or imagine this.

int size = 10;
int myArray[size];

size = 20;

How big is the array?

If you need dynamic arrays, use dynamic arrays.

Joseph Larson
  • 8,530
  • 1
  • 19
  • 36
  • 4
    " Arrays, for instance, are just a pointer to N pieces of memory" - no, they are not. Arrays are not pointers. –  Feb 25 '19 at 18:02
  • 1
    "If you need dynamic arrays, use dynamic arrays." - In the form of `std::vector`. – Jesper Juhl Feb 25 '19 at 18:10
  • Neil Butterworth, when you pass an array of integers, what are you passing? What word would you prefer I had used instead? Handle? That sounds very OO to me. If you can come up with a better way of putting it, feel free, and i can edit my response. – Joseph Larson Feb 25 '19 at 18:15
  • Jepser Juhl, personally I think it's worthwhile to know how to do your own dynamic use of memory rather than always relying on the stl. Furthermore, it depends just on how dynamic you need that data. If you're going to query a length value once and then populate what really isn't that dynamic, then maybe just new int[length] is perfectly reasonable. It all depends on context. – Joseph Larson Feb 25 '19 at 18:17
  • 2
    @JosephLarson you could be passing the array (by reference), a pointer to array or a pointer to the first element of the array. – SergeyA Feb 25 '19 at 18:17
  • SergeyA -- yes. Neil was picking on my semantics, and I'm challenging him to do more than tell me, "You're wrong" but to actually suggest better semantics. But the phrase "by reference" has particular meaning in C++. It means you are using the & symbol in the declaration, and so those semantics would bring confusion. When you pass an array in C or C++, you are passing -- as you said -- a pointer to the first element, or a pointer to the array (same thing). I don't think there's any difference under the hood between void foo(int *ptr) and void foo(int array[]). It's a pointer either way. – Joseph Larson Feb 25 '19 at 18:22
  • 1
    The difference between an array itself and the pointer it decays to is pretty important in the context of this particular question, which is about arrays themselves and not about using pointers to them. – hegel5000 Feb 25 '19 at 18:38
  • @hegel5000 That's also fine, but no one has suggested a better term to use in my original answer. They just keep downgrading it. – Joseph Larson Feb 25 '19 at 21:26
  • [An array is a contiguously allocated block of objects of the same type](https://en.cppreference.com/w/cpp/language/array). You pretty much said just that, but then you added the bit about pointers. – hegel5000 Feb 26 '19 at 00:25