I am trying to understand the difference between static and dynamic arrays in C++ and I can not think of a case where a static array would not do the trick.
I am considering a static array that would be declared this way:
int N=10;
int arr[N];`
I read here that the main difference between static and dynamic array is that a static array is allocated during compilation so N needs to be know at compilation.
However, this explains that arrays declared this way can also be Variable-length arrays:
Variable-length arrays were added in C99 - they behave mostly like fixed-length arrays, except that their size is established at run time; N does not have to be a compile-time constant expression:`
and indeed, the following c++ code is working, even though n is only known at runtime :
int n =-1;
std::cin>>n;
int arr[n];
//Let the user fill the array
for(int i=0; i<n;i++){
std::cin>>arr[i];
}
//Display array
for(int i=0; i<n;i++){
std::cout<<i<<" "<<arr[i]<<std::endl;
}
So I would like an example of code were a static arrays defined like this would not work and the use of dynamic array would be required ?
The code doesn't work on all compilers because variable length arrays aren't part of C++. They are part of C as of ISO C99, and some compilers will allow VLAs in C++, but it's not a portable solution. GCC, for instance, allows VLAs, but warns the user (-Wno-vla).
Below the hood, VLAs are dynamic anyway as the compiler can't reserve the appropriate amount of stack memory because it doesn't know how big the array is going to be. Instead of VLAs, std::vector can be used for dynamic memory that gets deallocated at the end of the scope.
Related
In C++ I tried declaring a global array of some size. I got the error:
array bound is not an integer constant before ‘]’ token
But when I declared an array of the same type in the main() function it is working fine.
Why is there different behaviour here?
int y=5;
int arr[y]; //When I comment this line it works fine
int main()
{
int x=5;
int arr2[x]; // This line doesn't show any error.
}
Edit: Many are suggesting this question is a duplicate of Getting error "array bound is not an integer constant before ']' token". But that question doesn't answer why there is different behaviour.
Both examples are ill-formed in C++. If a compiler does not diagnose the latter, then it does not conform to the standard.
Why there is a different behaviour here?
You use a language extension that allows runtime length automatic arrays. But does not allow runtime length static arrays. Global arrays have static storage.
In case you are using GCC, you can ask it to conform to the standard by using the -pedantic command line option. It is a good idea to do so in order to be informed about portability problems.
The size of an array must be a constant. You can fix this by declaring y as const.
const int y=5;
int arr[y];
As for why this worked in main, g++ does allow a variable length array in block scope as an extension. It is not standard C++ however.
Both shouldn't be used, one works because (as #eerorika said) automatic length arrays are allowed on runtime, but global arrays need to have static storage.
If you want to declare an array with a variable size (e.g. given by std::cin) you would do something along the lines of:
int x;
std::cin >> x;
const int n = x;
float arr[n];
But you wouldn't be able to set it to contain just zeros with float arr[n] = {0} (if you need to add to a value in the array, not being sure you set it), you would need to use a loop like that
for(int i = 0; i < n; i++)
{
arr[i] = 0;
}
The type-system of C++ handles these C-like arrays in a way that it defines arr2 from your example of type int[5]. So, yes the number of elements of the array is part of the type!
This puts some constraints on what you are allowed to use in the definition of C-like arrays. I.e. this number needs to have static storage, needs to be immutable and needs to be available at compile time.
So, you might want to change your code to something like the following, which will have another goodie. It initializes the array in a proper way:
int arr2[] = {0, 0, 0, 0, 0};
What is the difference between this two array definitions and which one is more correct and why?
#include <stdio.h>
#define SIZE 20
int main() {
// definition method 1:
int a[SIZE];
// end definition method 1.
// defintion method 2:
int n;
scanf("%d", &n);
int b[n];
// end definition method 2.
return 0;
}
I know if we read size, variable n, from stdin, it's more correct to define our (block of memory we'll be using) array as a pointer and use stdlib.h and array = malloc(n * sizeof(int)), rather than decalring it as int array[n], but again why?
It's not "more correct" or "less correct". It either is xor isn't correct. In particular, this works in C, but not in C++.
You are declaring dynamic arrays. Better way to declare Dynamic arrays as
int *arr; // int * type is just for simplicity
arr = malloc(n*sizeof(int*));
this is because variable length arrays are only allowed in C99 and you can't use this in c89/90.
In (pre-C99) C and C++, all types are statically sized. This means that arrays must be declared with a size that is both constant and known to the compiler.
Now, many C++ compilers offer dynamically sized arrays as a nonstandard extension, and C99 explicitly permits them. So int b[n] will most likely work if you try it. But in some cases, it will not, and the compiler is not wrong in those cases.
If you know SIZE at compile-time:
int ar[SIZE];
If you don't:
std::vector<int> ar;
I don't want to see malloc anywhere in your C++ code. However, you are fundamentally correct and for C that's just what you'd do:
int* ptr = malloc(sizeof(int) * SIZE);
/* ... */
free(ptr);
Variable-length arrays are a GCC extension that allow you to do:
int ar[n];
but I've had issues where VLAs were disabled but GCC didn't successfully detect that I was trying to use them. Chaos ensues. Just avoid it.
Q1 : First definition is the static array declaration. Perfectly correct.
It is when you have the size known, so no comparison with VLA or malloc().
Q2 : Which is better when taking size as an input from the user : VLA or malloc .
VLA : They are limited by the environment's bounds on the size of automatic
allocation. And automatic variables are usually allocated on the stack which is relatively
small.The limitation is platform specific.Also, this is in c99 and above only.Some ease of use while declaring multidimensional arrays is obtained by VLA.
Malloc : Allocates from the heap.So, for large size is definitely better.For, multidimensional arrays pointers are involved so a bit complex implementataion.
Check http://bytes.com/topic/c/answers/578354-vla-feature-c99-vs-malloc
I think that metod1 could be little bit faster, but both of them are correct in C.
In C++ first will work, but if you want to use a second you should use:
int size = 5;
int * array = new int[size];
and remember to delete it:
delete [] array;
I think it gives you more option to use while coding.
If you use malloc or other dynamic allocation to get a pointer. You will use like p+n..., but if you use array, you could use array[n]. Also, while define pointer, you need to free it; but array does not need to free.
And in C++, we could define user-defined class to do such things, and in STL, there is std::vector which do the array-things, and much more.
Both are correct. the declaration you use depends on your code.
The first declaration i.e. int a[size]; creates an array with a fixed size of 20 elements.
It is helpful when you know the exact size of the array that will be used in the code. for example, you are generating
table of a number n up till its 20th multiple.
The second declaration allows you to make an array of the size that you desire.
It is helpful when you will need an array of different sizes, each time the code is executed for example, you want to generate the fibonacci series till n. In that case, the size of the array must be n for each value of n. So say you have n = 5, in this case int a [20] will waste memory because only the first five slots will be used for the fibonacci series and the rest will be empty. Similarly if n = 25 then your array int a[20] will become too small.
The difference if you define array using malloc is that, you can pass the size of array dynamically i.e at run time. You input a value your program has during run time.
One more difference is that arrays created using malloc are allocated space on heap. So they are preserved across function calls unlike static arrays.
example-
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
int *a;
scanf("%d",&n);
a=(int *)malloc(n*sizeof(int));
return 0;
}
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.
I want to initialize an array with a size using a value I read into an integer variable.
I cant seem to understand why it works in Dev-C++ but not in Turbo C++. Here's the code to help make things clear
int arr_size; //cin max value for lets say number of students or something...
cin >> arr_size;
int array[arr_size]; // declares array with size (assume 10 or 100) with range 0 to 9 or 0-99
The compiler shows an error in Turbo C++ (really old, I know, but my school uses it unfortunately). Dev-C++ and codeblocks doesnt.
Why is that so? I know its bad practice "as they define it in some books" to have an array size the same as an int value, but is there a work around for this in Turbo C++?
I want to know why the error happens and how I can get a work around it ... thanks a lot!
The C++ standard only permits arrays to be sized with a constant expression. (However, some compilers may offer it as a non-standard language extension.)
You could use a std::vector instead:
std::vector<int> array(arr_size);
Or you could dynamically-allocate memory manually:
int *const array = new int[arr_size];
...
delete [] array; // Remember to delete when you're done
Variable length arrays are not allowed in standard c++. You can do it in C99. Consider using C++ std::vector as :
std::vector<int> array(arr_size);
And you can index it exactly like the array if you have to.
The workaround is to dynamically allocate this array, making sure to delete the memory when done.
int arr_size; //cin max value for lets say number of students or something...
cin >> arr_size;
int *arr = new int[arr_size];
//use the array as needed
delete [] arr;
You want variable length array (VLA) which is not allowed in C++. Its allowed in C99.
Use std::vector<int> instead, as:
int arr_size;
cin >> arr_size;
std::vector<int> array(arr_size);
Is there any way of creating a static array in c++ at run time.
What i want is really simple like just want to get input number from user and create a static array of size of input number at run time. No new operator is required no pointer are required just static array?
No. static variable is allocated before the program code is actually running (i.e.: before your main is called). What you need is a dynamic (aka created at run time) array. If you want to avoid new you can create it on stack (by passing parameter to a function that will create it and working on it within that function), but that's not the same as static. You can also use template containers that will do the allocation and resizing for you (like std::vector, mentioned in other answers)
edit
It seems to bother some people that I didn't mention the matter of initializing static objects. Although not directly relevant to the question - worth to know that static member variables or static variables within a scope can be initialized at run time, but the space for them is reserved prior to the main, so the size of the variable cannot be changed.
If you mean
unsigned size;
std::cin >> size;
int arr[size];
Then: No. C99 has a feature called Variable-Length-Arrays, but the C++03 (and '0x) standard have no notion of this kind of feature.
Use alloca to allocate space on the stack, just like a static array or like a C99 variable length array.
#include <iostream>
#include <alloca.h>
int main() {
unsigned sz;
std :: cin >> sz;
int * p = static_cast<int*>(alloca(sz * sizeof(int)));
// do stuff with p, do not attempt to free() it
}
I've only ever used it with C, but it works well. Read about it first though. It probably isn't very portable.
No.
By definition, you need to dynamically allocate anything whose size is not known until runtime. That's why new and friends exist.
What does it mean to you that an array is static? What advantages do you think it gives you?
Actually, any static variable (including arrays) has its storage reserved at the beginning of the program. For this reason, its size has to be known before the program starts running, so it can't depend on user input in any way.
There are a number of ways to make dynamic non-static arrays, however, so let us know what you're trying to do.
It sounds like what you want is an array whose size is run-time defined but whose life time is defined by static storage duration (ie the length of the program).
You can not use the basic array built into the language. The size of these objects are defined at compile time and can not be modified at run-time. But there are a couple of alternatives.
The basic std::vector is probably what you want:
std::vector<int> data;
int main()
{
int size;
std::cout << "Input the size of the array\n";
std::cin >> size;
// This line sets the size of the container
// vector is basically a C++ wrapper around a dynamically sized array
data.resize(size);
// Now we can safely read values into the array (like) container.
for(int loop =0;loop < size;++loop)
{
std::cout << "Input Value " << loop << "\n";
std::cin >> data[loop];
}
}