Allocating arrays in C++ [duplicate] - c++

This question already has answers here:
In C++ books, array bound must be constant expression, but why the following code works?
(2 answers)
Closed 9 years ago.
When I started programming with C++ I was learned to allocate the array size by using dynamic memory allocation as follows:
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
int *nArray = new int[nArrayLength];
// contents
delete[] nArray;
return 0;
}
Now I tried the following code using Code::Blocks 12.11 with the mingw32-g++ // GNU GCC compiler.
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
int nArray[nArrayLength];
return 0;
}
This also works fine.
Therefore, why should I use dynamic memory allocation in this case when the easier method also works fine?

You should use neither.
The first is valid, but it's C-style code. The second is non-standard code - it's accepted by that compiler because of some extension.
Use a std::vector instead:
#include <vector>
int main()
{
int nArrayLength;
cout << "Enter an array length: ";
cin >> nArrayLength;
std::vector<int> nArray(nArrayLength);
return 0;
}
A vector has the same semantics as an array, it can grow dynamically (and automatically), and does all the pesky memory management under the hood.

The second code is not valid standard C++. It uses a compiler extension called variable length arrays. See the GCC documentation.
However, there is a proposal for variable length arrays with automatic storage duration that has been adopted for C++14.

Compile the second code with -pedantic option if you're using GCC. It would not compile.
It is because it is not Standard conformant. Variable Length Array (VLA) is not in the Standard C++. It is a compiler extension.

Sometimes you don't know the size of your array beforehand, so you need to allocate storage for it that may grow or shrink dynamically. You should use std::vector because it manages the array storage transparently.
If you are forced to use C-style arrays, use them like in the first code snippet, the second one is not standard C++.

It depends whether you want to use the stack or the heap.
You can also use auto_ptr if you want your heap allocation to be released automatically when scope goes out.

Related

What are different ways of initializing the size of an array with user input in c++

I was wondering what are some alternatives to doing the following code snippet in c++.
int i;
cin >> i;
int arr[i];
I have recently started looking into competitive programming and trying to learn more.
EDIT: For those comments about this not being cpp. It compiles successfully with the makefile I am using in my class which is using gcc -std=c++11 -o a.exe main.cpp and returns to the console when I input a length of 1
array length: 1
You should use std::vector instead in C++, e.g.
int i;
cin >> i;
std::vector<int> arr(i);
BTW: VLA is not supported by C++ standard. Also see Variable Length Array (VLA) in C++ compilers
One way is:
int i = 0;
cin >> i;
auto arr = std::make_unique<int[]>(i); // #include <memory>
// Or: std::make_shared<int[]>(i);
Another way is to use std::vector:
int i = 0;
cin >> i;
std::vector<int> arr(i); // #include <vector>
Your code is not C++. It uses a C language feature (from the C99 version of the C standard) called "variable-length arrays" - where arrays on the stack can have a length determined at run-time.
Variable-length arrays are considered are dangerous and considered a rather bad idea; see:
Why aren't variable-length arrays part of the C++ standard?
If you compile your code while telling the compiler to only accept standard-compliant code, it will fail: gcc -std=c++11 -pedantic-error. Try it on GodBolt.
In C++ the size of an array is set at compile-time, period. Like other users suggested, you can use dynamic allocation to obtain a run-time-determined-length contiguous area in memory, of your choice of size: Using std::vector, std::unique_ptr, std::shared_ptr or even plain allocation with new (although the latter is not recommended).

Why do I need dynamic memory allocation if I can just create an array? [duplicate]

This question already has answers here:
Declaring the array size with a non-constant variable
(2 answers)
Closed 4 years ago.
I was reading about dynamic memory allocation and static memory allocation and found the following about dynamic memory allocation:
In the programs seen in previous chapters, all memory needs were determined before program execution by defining the variables needed. But there may be cases where the memory needs of a program can only be determined during runtime. For example, when the memory needed depends on user input.
So I wrote the following program in C++:
#include <iostream>
int main()
{
int n = 0;
int i = 0;
std::cout << "Enter size: ";
std::cin >> n;
int vector[n];
for (i=0; i<n; i++)
{
vector[i] = i;
}
return 0;
}
This program works.
I don't understand how it works.
When is the size determined here?
How does the vector get allocated in this case?
According to this (emphasis mine):
Variable-length automatic arrays are allowed in ISO C99, and as an
extension GCC accepts them in C90 mode and in C++. These arrays are
declared like any other automatic arrays, but with a length that is
not a constant expression. The storage is allocated at the point of
declaration and deallocated when the block scope containing the
declaration exits.
Note that this is just an extension and won't work on every compiler, for instance it doesn't work for me in MSVC (I get the error "expression must have a constant value").
Above Code Will Generate error in latest version of compiler.This Code will Work in old version of DOSBOX.
Array's Size Must be Constant Integer.
So you can define it using two ways
1.#define Macron
#include<iostream>
#define n 5
main() {
...
...
int array[n];
}
2.const keyword
#include<iostream>
....
main() {
int x;
cout << "Enter Size Of Array";
cin >> x;
const int n = x;
int array[n];
...
...
}

2-D Array - Expression must have a constant value error

I'm attempting the Latin Square Daily Challenge on Reddit and I wanted to use an array which allocates size during run-time by using the following code:
int n;
cout << "Please enter the size of the Latin Square: ";
cin >> n;
int latinsquare[n][n];
This works in online compilers but not in Visual Studio 17. Is there a way to do this in the Microsoft C++ compiler?
This is because variable-length arrays are non-standard in C++ (why?). You can allocate latinsquare using new, but an idiomatic way of doing it in C++ is to use a vector of vectors:
std::vector<std::vector<int>> latinsquare(n, std::vector<int>(n, 0));
VLA is not a part of c++ standard. If you want to use them you need compiler extension.
But you may
Create it dynamically via new and delete operators
Use std::vector

C++: Why does int array[size] work?

I have started learning c++. I read that an array's size can only be set before run and dymanic arrays can be set during runtime. So I was expecting this to fail but it didn't:
#include <iostream>
int main() {
using namespace std;
int size;
cout << "enter array size:";
cin >> size;
int i, score[size], max; //array size set to variable doesn't fail
cout << endl << "enter scores:\n";
cin >> score[0];
max = score[0];
for (i = 1; i < size; i++)
{
cin >> score[i];
if (score[i] > max)
max = score[i];
}
cout << "the highest score is " << max << endl;
return 0;
}
Is this a new feature in recent C++ compilers? Is it realising I need a dynamic array and creating that instead?
Probably you are using GCC compiler, it has an extension called Arrays of Variable Length.
std::vector is the real dynamic arrays in C++.
To select this standard in GCC, use the option -std=c++11; to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if you want them to be errors rather than warnings).
In all current and past standards, that code is ill-formed. Variable Length Arrays are a C99 feature not a C++ feature, although some compilers do provide it as an extension. In the upcoming standard (expected to be C++14, currently in the process of review) a similar feature by other name (and slightly different semantics) has been adopted, so expect this to become standard in the future.
Note that in general, that is, excluding arrays of runtime bound (as they are named in the upcoming standard), the size of the array is part of the static type of the object and known at compile time. In the case of VLAs or array of runtime bound, the size is not known at compile time and thus the type is somehow of a second class citizen among types. The implication is that you cannot use VLAs/ARB with templates (as code generation for the template depends on the type, which includes the size, which is unknown at compile time).
In the same way there are other limitations, sizeof is not a compile time operation for VLAs, and it is not even allowed for ARB, these form of arrays can only be used for objects with automatic storage duration (i.e. in the stack), you cannot take the address of the array (although you can take the address of the first member),...
Another important point to consider is that the standard does not guarantee that the memory for an ARB will be allocated on the stack, and allows implementations to call a global allocation function, although the intention is that compilers will catch up and provide the space from the stack.
Be careful! Undefined integers are not guarenteed to be any value at all. Some compilers will default to 0, while others will use whatever garbage bits where already in memory. For this reason Visual Studio wouldn't even let me compile. Step through your code to see the allocated memory for score before you set the size variable. Likely size as it is compiled is a random integer from garbage memory, which means it can change every time you execute!
A C style array needs to know how much continuous memory to allocate. This allows for direct indexing, and other optimizations. As others have suggested, std::vector is what is the standard dynamic container in C++, which uses an array under the hood.

Dynamic allocation

Is it possible to mimic the behavior of dynamic allocation using the following code. For example we do not know the exact number of the integer that are stored in a file and we are going to read the file and then store it in an array called Hello.
int x;
int n=0;
ifstream input("a.dat");
while (!input.eof())
{
input >> x;
n++;
}
input.close();
int Hello[n];
cout << "n= " << n << endl;
int i=0;
while (!input.eof())
{
input >> Hello[i];
i++;
}
Is it possible to mimic the behavior of dynamic allocation using the
following code.
No, the major difference is that the array in your program is stored on stack, whereas all dynamic memory allocations takes place on heap.
What you are exactly doing, in your code is using the VLA feature of C99 standard of C in C++. Compiling with the -pedantic option in g++ compiler will reveal this. Since it is not directly supported by c++, and it is a implementation-specific language extension, its not such a good idea to use it, if you aim to write portable code.
VLA's use alloca() , to allocate memory on stack at runtime, and the disadvantages of such a tecnnique are discussed here.
Further more, VLA's allocate memory on stack during runtime, and if the value exceeds the range, the program simply crashes, while it is ok to quickly create a few bytes of array using VLA's , creating uncertain amounts of large memory may not be safe, and it is best to handle it using dynamic memory allocation.
int Hello[n];
is NOT dynamic allocation. It is required that n is a compile time constant if you want to declare Hello in this way.
try:
int* Hello = new int[n];
and don't forget to release the memory when you are done using it:
delete[] Hello;
This is allowed as an extension by some compilers, but is not strictly part of C++.
int Hello[n];
As an alternative, you can allocate the memory yourself:
int* Hello = new int[n];
And free it yourself also:
delete[] Hello;
But you can avoid manual memory management by usng std::vector from <vector>. One of its constructors accepts an initial size:
vector<int> Hello(n); // Vector with n elements, all initially 0.
You can also set an initial capacity without resizing, to do the allocation once:
vector<int> Hello; // Empty vector.
Hello.reserve(n); // Allocate space for n elements; size() is still 0.
Then read into an int and use push_back to insert values:
int value;
while (input >> value)
Hello.push_back(value);
Note the use of input >> value as the loop condition—this reads as long as reads are successful. eof() returns true only when the last read operation failed due to unexpected end of file, which is unlikely to be exactly what you want.
For a start the second
while (!input.eof())
Will always fail. That terminated the first one and then you set about closing that input stream!