2

Ever since I started the competitive programming, I always found that people always used to initialize the single or 2D arrays based on a constant maximum value from the maximum value of the input specification.

But I've always wondered why people do that when you can initialize the array based on the input.

For example, let's say a problem has an input specification of zero to ten to the power of five when receiving the input for the size of an array (or a vector).

Why do people do this:

Notation: The integer n represents the input, and a represents the array:

#include<bits/stdc++.h>

using namespace std;

const int MXN = 1e5;
int a[MXN], n;

int main() {
    cin >> n;

    for(int i = 0; i<n; i++)
        cin >> a[i];
}

Instead of this:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;

    int a[n];

    for(int i = 0; i<n; i++)
        cin >> a[i];
}

Or is this the best method (which is what I normally do):

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int>a(n);

    for(int i = 0; i<n; i++)
        cin >> a[i];

    //for(auto &i:a) cin >> i;
}

Is there any advantages of doing this? Thank you.

Rohan Bari
  • 6,523
  • 3
  • 9
  • 30
Rainier1
  • 63
  • 6
  • The reason is simple: your 2nd example is invalid C++. – Algirdas Preidžius Jul 02 '20 at 07:23
  • 1
    The first snippet is a waste of memory or a out-of-bounds access, the second snippet is no standard C++. Neither of them should be used, use `std::vector`. (technically none of them is standard C++, because of [this header](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h)). – churill Jul 02 '20 at 07:23
  • 3
    First of all because you're looking at code from "competition" sites, where people don't know about good programming practices, and use many bad habits (including the one you propose). Also [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array) aren't part of standard C++. – Some programmer dude Jul 02 '20 at 07:24
  • 4
    On very related notes, please read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) as well as [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Some programmer dude Jul 02 '20 at 07:25
  • 2
    Lastly please don't use competition sites as a learning or teaching resource, or as repositories of good code to learn from, because they're *not* (I would argue that they're quite the opposite). Take classes, read [some good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282), learn properly before using such sites. – Some programmer dude Jul 02 '20 at 07:28
  • 1
    The only "advantage" (I use the term loosely) of these techniques are that they are accepted on competitive programming sites. Continue using such approaches if you wish to learn programming techniques that are bad practice in the real world, and will have to be unlearned if you ever hope to get a half-decent job as a programmer doing work you can be proud of. – Peter Jul 02 '20 at 07:35
  • @churill I normally use a vector when initialising arrays. When initialising arrays I normally use the "auto" method and receive my input from there. I was just confused about why some people do this. – Rainier1 Jul 02 '20 at 07:41
  • @Rainier1 Good, stick to it, it's far easier to use and more robust than "competetive methods", indeed the last snippet is the best (Except for `#include ` which is bad in any case) – churill Jul 02 '20 at 07:47
  • "Competitive programming" teaches lots of bad habits. – Pete Becker Jul 02 '20 at 13:23

2 Answers2

2

The 3 methods have their own advantage and disadvantage. The choice depends on the goal.

First method: a static storage duration array

  • The array last for the duration of the program execution,
  • Memory allocation is performed at program start up (probably by the os), and is very cheap
  • It does not provide value semantic. (It can't be easily copied, moved or assigned).

This method may be good for execution speed in small project but it is not scalable.

Second method: array allocated on the stack

  • The array life time start at its definition and end at the block scope exit
  • Memory allocation is performed during program execution and consist only of a very cheap assembly instruction.
  • It does not provide value semantic. (It can't be easily copied, moved or assigned).
  • It is a compiler extension to the standard language.

This method can be a good choice for temporary buffer, but once again it is not scalable, it is known to be a cause of stack overflow.

Third method: dynamically allocated array, std::vector

  • The array life time start and ends when needed,
  • Memory allocation is performed during program execution and is relatively expensive
  • It does provide value semantic. (It can easily copied, moved or assigned).

This should be the default choice.

Oliv
  • 16,492
  • 1
  • 24
  • 63
0

The standard requires the array length to be a value that is compute-able at compile time so that the compiler is able to allocate enough space on the stack.

In your case, you're trying to set the array length to a value that is unknown at compile time. Yes, it seems obvious that it should be known to the compiler, but this is not the case here. The compiler cannot make any assumptions about the contents of non-constant variables.

This is one of the highlighted reason why we should use constants to declare the array size so that compiler would know how much memory on the stack should be allocated during creating the array.

For the dynamic allocation, either we may use data_type variable = new data_type[len] format or vector<>. Notice that the VLAs are supported in C99 (about the way you're trying to declare array like arr[n]).

As an instance, suppose if you tell the compiler

int vla = 100;
int a[vla];

The compiler would've no way of thinking how much memory you're actually going to need at runtime without doing a lot of very complex analysis to track down every last place where the values of vla changed.

Rohan Bari
  • 6,523
  • 3
  • 9
  • 30