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!
Related
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.
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.
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.
Suppose I have the following snippet.
int main()
{
int num;
int* cost;
while(cin >> num)
{
int sum = 0;
if (num == 0)
break;
// Dynamically allocate the array and set to all zeros
cost = new int [num];
memset(cost, 0, num);
for (int i = 0; i < num; i++)
{
cin >> cost[i];
sum += cost[i];
}
cout << sum/num;
}
` `delete[] cost;
return 0;
}
Although I can move the delete statement inside the while loop
for my code, for understanding purposes, I want to know what happens with the code as it's written. Does C++ allocate different memory spaces each time I use operator new?
Does operator delete only delete the last allocated cost array?
Does C++ allocate different memory spaces each time I use operator new?
Yes.
Does operator delete only delete the last allocated cost array?
Yes.
You've lost the only pointers to the others, so they are irrevocably leaked. To avoid this problem, don't juggle pointers, but use RAII to manage dynamic resources automatically. std::vector would be perfect here (if you actually needed an array at all; your example could just keep reading and re-using a single int).
I strongly advise you not to use "C idioms" in a C++ program. Let the std library work for you: that's why it's there. If you want "an array (vector) of n integers," then that's what std::vector is all about, and it "comes with batteries included." You don't have to monkey-around with things such as "setting a maximum size" or "setting it to zero." You simply work with "this thing," whose inner workings you do not [have to ...] care about, knowing that it has already been thoroughly designed and tested.
Furthermore, when you do this, you're working within C++'s existing framework for memory-management. In particular, you're not doing anything "out-of-band" within your own application "that the standard library doesn't know about, and which might (!!) it up."
C++ gives you a very comprehensive library of fast, efficient, robust, well-tested functionality. Leverage it.
There is no cost array in your code. In your code cost is a pointer, not an array.
The actual arrays in your code are created by repetitive new int [num] calls. Each call to new creates a new, independent, nameless array object that lives somewhere in dynamic memory. The new array, once created by new[], is accessible through cost pointer. Since the array is nameless, that cost pointer is the only link you have that leads to that nameless array created by new[]. You have no other means to access that nameless array.
And every time you do that cost = new int [num] in your cycle, you are creating a completely new, different array, breaking the link from cost to the previous array and making cost to point to the new one.
Since cost was your only link to the old array, that old array becomes inaccessible. Access to that old array is lost forever. It is becomes a memory leak.
As you correctly stated it yourself, your delete[] expression only deallocates the last array - the one cost ends up pointing to in the end. Of course, this is only true if your code ever executes the cost = new int [num] line. Note that your cycle might terminate without doing a single allocation, in which case you will apply delete[] to an uninitialized (garbage) pointer.
Yes. So you get a memory leak for each iteration of the loop except the last one.
When you use new, you allocate a new chunk of memory. Assigning the result of the new to a pointer just changes what this pointer points at. It doesn't automatically release the memory this pointer was referencing before (if there was any).
First off this line is wrong:
memset(cost, 0, num);
It assumes an int is only one char long. More typically it's four. You should use something like this if you want to use memset to initialise the array:
memset(cost, 0, num*sizeof(*cost));
Or better yet dump the memset and use this when you allocate the memory:
cost = new int[num]();
As others have pointed out the delete is incorrectly placed and will leak all memory allocated by its corresponding new except for the last. Move it into the loop.
Every time you allocate new memory for the array, the memory that has been previously allocated is leaked. As a rule of thumb you need to free memory as many times as you have allocated.
I have seen examples showing the basic usage of dynamic arrays like that
int main()
{
int n;
int *array;
std::cin >> n;
array = new int[n];
delete [] array;
return 0;
}
but I can do
int main()
{
int n;
std::cin >> n;
int array[n];
return 0;
}
to create static array and let the user define its size. So what advantage of dynamic arrays that example shows?
The first is poor C++ coding style. A better solution is:
int main() {
int n;
std::cin >> n;
std::vector<int> array(n); // or std::unique_ptr<int[]> array( new int[n] );
return 0;
}
which gives you RAII and clear buffer ownership.
The second example you give is not legal C++. Your compiler may support it as an extension (either because of the future proposal, because of compatibility with C, or for whatever other reason). There are proposals to add this syntax to a future C++ version. It is legal C under the current standard, but C++ is not a superset of C.
Under the proposed version, int array[n] creates an array in automatic storage that goes out of scope when the current scope ends. This means it must exist within a scope, and it cannot exceed that scope's lifetime -- the std::vector and std::unique_ptr solutions above can have the buffer outlive the current scope.
Another solution for a future version of C++ is std::dynarray<int> which represents a value-semantics buffer. Like int array[n] its buffer cannot live beyond the end of the current scope, but at least it can be returned from a function (and its data copied) without jumping through hoops.
One other problem with automatic storage solutions is that stack space is sometimes much more limited than heap space (the free store). So sticking large amounts of stuff on the stack is dangerous. In addition, there are ways to catch allocations failures on the heap, but protection against stack overflow in C/C++ is less robust.
A final problem with int array[n] is that C style arrays have strange semantics when passed to functions and the like (with their pointer-decay) that sometimes gets in the way.
Variable length arrays are a GCC extension. So, your code isn't portable. It would be a good practice to pick an appropriate STL container, unless the overhead is absolutely unacceptable. In that case, stick to your first code snippet.
This question already has answers here:
What is the difference between Static and Dynamic arrays in C++?
(13 answers)
Closed 9 years ago.
I'm a beginer. I'm confused about the difference between them. I have read a few answers and realized one of the difference is that the dynamic array can be deleted while the normal array can't. But are there any other differences? Such as their functions, sizes or whatsoever?
Well I have read such an example, and I don't see any difference if I replace the dynamic array {p= new (nothrow) int[i];} with a normal array {int p [i];}.
#include <iostream>
#include <new>
using namespace std;
int main ()
{
int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int[i];
if (p == 0)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
But are there any other differences?
Compile and run this, see what happens:
int main(int argc, char** argv){
char buffer[1024*1024*64];
buffer[0] = 0;
return 0;
}
Explanation:
Well, normal array is placed either on stack or within code segment (if it is global variable or static local variable). At least on windows/linux PCs. The stack has limited size (although you can change it using ulimit in linux and compiler settings on windows). So your array is too big for the stack, your program will instantly crash upon entering the function with that array ("segmentation fault" on linux, "stack overflow" or "access violation" on windows (forgoet which one)). Default limit for array size is 1Megabyte on windows (x86), and 8 megabytes on linux.
You cannot determine size of a block allocated with new. int *p = new int[146]; std::cout << sizeof(p) << std::endl. will print sizeof(int*), not size of allocated memory. However, sizeof works on arrays.
Theoretically, using dynamic memory allocation, you can allocate as much memory as you want (operating system may impose limits, though, and on 32bit system maximum allocated block size will be 2..3 GB). You can also control resource usage by freeing the memory, so your program won't be eating system ram/swap file for no reason.
Dynamic arrays are not automatically freed, you have delete them manually.
That's just a brief overview.
Dynamic memory allocation provides finer resource control and removes some limitations of local variables.
Speaking of which, although you CAN use new/delete, if you want to use arrays with variable size, you should use std::vector instead. Manual memory management is prone to errors, so you should make compiler do it for you when possible. As a result, it is advised to at least study STL(Standard Template Library) , smart pointers, RAII, Rule of Three.
Dynamic is just that. You can change the size of the resulting array at runtime rather than compile time. There are compiler extensions that allow you to use static arrays (int array[CONSTANT]) like a dynamic array in that you can specify the size at runtime but those are nonstandard.
Dynamic arrays are also allocated on the heap rather than the stack. This allows you to use all of the available memory if necessary to create the array. The stack has a limited size that depends on the OS.
Allocating memory on the heap allows you to for example do this:
int* createArray(int n) {
int* arr = new int[n];
return arr;
}
int main()
{
int* myArray = createArray(10);
// this array is now valid and can be used
delete[] myArray;
}
I'm sure there are numerous other intricacies between dynamic vs static arrays but those points are the big ones.
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];
}
}