Difference between int someInts[3] and int* someInts = new int[3]? - c++

What is the difference between declaring a new integer array by using int someInts[3], versus using int* someInts = new int[3]?

There are 2 main differences:
The first will allocate a memory on the stack, that will be unavailable once the function returns.
The second will allocate a memory on the freestore, which will be available until deleted.
The first someInts is an array of ints, you cannot assign new address to it.
The second is a pointer to int, so you may assign a new address to it.

The difference that's generally important (especially when you're dealing with something other than ints) is that with when you use the latter (int *someints = new int[3];) you have to explicitly delete the data when you're done using it.
Most of the time, you want to use std::vector<int> someints(3); instead. This will (normally) allocate the space for the data similarly, but it'll automatically delete that space when the variable goes out of scope (including, for example, leaving the scope via an exception being thrown, which is much more difficult to handle correctly when you allocate/free the memory manually).

Declaring int* someInts = new int[3] allocates the memory on the heap. Declaring int someInts[3] allocates it on the stack.

When you do someInts[3], you allocate memory on the stack, this means that it will delete itself (good) but if you want to access after the function has ended you'll run into trouble as it will already have been deleted. IE:
int* returnPointerThingy(){
int someInts[3];
someInts[0] = 3;
someInts[1] = 2;
someInts[2] = 1;
return someInts
}
This will return a null pointer since someInts has been deleted. If you try to access something in someInts god help you.
If this is similar to what you which to do you want to use the new keyword. It will allow you to allocate something on the "Heap" and it will live after the function it was declared in has ended. Thus this:
int* returnPointerThingy(){
int* someInts = new int[3];
someInts[0] = 3;
someInts[1] = 2;
someInts[2] = 1;
return someInts
}
Will not return a null pointer and you will be able to use the values stored by someInts. However this comes with a drawback, you must delete someInts like this:
delete [] someInts
So you don't end up with memory leaks, when the heap gets taken up by pointers and such.
It depends on your situation for which to use as both are better in their own situations.

Related

Program crashes when deleting a pointer pointing to the heap?

If I go...
int *foo = new int;
foo += 1;
delete foo;
Most of the time it crashes. Is there a reason for this? I'm trying to have the pointer point one spot forward (4 bytes). Thanks.
Edit (six months later): This was the first question I asked on SO, and it was a silly question and deserved the downvotes. It can be deleted if it's of no use to learners. I was indeed talking about allocating an int of four bytes on the heap, then moving the pointer four bytes forward, and then deleting the int pointer, essentially deleting God knows what, leading to undefined behaviour. Thanks for your help.
The only thing you can safely pass to delete is something you got when you called new, or nullptr, in that case the delete won't do anything.
You changed the value of the pointer - therefore it isn't "something you got when you called new"
You must pass to delete the value that new returned. You don't do that.
I think that you are confused as to what you are passing to delete. I think that you believe that delete foo will delete the memory associated with the variable. It doesn't. It deletes the memory whose address is stored in foo.
As an example, this is legitimate:
int* foo = new int;
int* bar = foo;
delete bar;
What matters is not the name of the variable, but rather the value of the variable.
Here's another example:
int* arr = new int[10];
int* ptr = arr;
for (int i; i < 10; i++)
{
*ptr = i;
ptr++;
}
delete[] arr;
In order to perform pointer arithmetic, and retain the address returned by new[], we introduced an extra variable. I used an array because it doesn't make sense to perform arithmetic on a pointer to a single value.
Note that in the code above, it could be written more clearly using arr[i] = i and so avoid the need for a second pointer variable. I wrote it as above to illustrate how you might code when pointer arithmetic is the right option.

Create a pointer on the Stack

I'm learning C++ and I have a question about pointers.
I have this code:
int* max = new int;
*max = 0;
I think, I have created a pointer on the heap (if I'm not right, please, tell me).
One question:
Is there a way to create an initialize a pointer with one instruction? (now, I'm using two instructions).
Another question:
How can I create a pointer on the stack?
I see code like this one:
int myVar = 20;
int* pVar = &myVar;
I think I haven't created a pointer on the stack but I think it is the only way to not create a pointer on the heap.
I'm very very very new on C++ development.
int* max = new int;
The above line creates a pointer on the stack and initializes it with an integer stored on the heap. Whenever new is involved in an expression, it will return a pointer to its dynamically-created operand:
Per Paragraph 5.3.4/2 of the C++11 Standard:
Entities created by a new-expression have dynamic storage duration (3.7.4). [ -- ] If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
int myVar = 20;
int* pVar = &myVar;
In this example, both the pointer and its value is stored on the stack. A new-expression was not involved in the assignment, so nothing is created on the heap in this situation.
If you want to initialize the value of the pointed-to object in one line, you'd have to value-initialize it like so:
int* max = new int(5);
or in C++11 you can use uniform-initialization:
int* max = new int{5};
It is also important that you remember to delete that which you created with new. Since the memory is in dynamic allocation, its lifetime is not dependent by the scope in which it was created. If you forget to delete your program will get a memory leak.
delete max;
And if max was a pointer set to an array created by a new-expression, you'd use delete[]:
delete[] max;
Note: If a pointer was not initialized by a new-expression, then there is no need to delete.
It's typically recommended that you use containers to mangage the memory for you. Something like std::unique_ptr will do. Once its destructor is called, the memory it holds is deleted:
std::unique_ptr<int> max{new int{5}};
In C++14 we have make_unique:
auto max = std::make_unique<int>(5);
Pointers are normal variables, which content is a memory address. This memory can be heap memory or stack memory. Don't confuse the pointer with the memory space it points to.
Your first code allocates space on the heap which can hold an int. You store a pointer to that memory on the stack.
Your second code allocates space on the stack which can hold an int. You store a pointer to that memory on the stack.
So both pointers are on the stack, but only the second points to the stack.
In both cases, the type you allocate is a primitive type. Primitive types aren't initialized per default, unless you immediately assign a value to it (your second code), or use the constructor syntax, which also works with heap-allocated values:
int *max = new int(0);
The same syntax can be used in your second code, by the way:
int myVar(20);
In case you're interested: You can also define pointers on the heap. int* is the type of pointers to ints, so just go ahead and allocate such a type on the heap:
new int*();
This expression returns an int**, which you can then store somewhere. Again, you typically store this pointer-to-pointer on the stack:
int **pointerToPointer = new int*();
As with ints, you can initialize an int* in the new-expression to some pointer-to-int (here, the max pointer from above):
int **pointerToPointer = new int*(max);
Now you have two pointers with the same address: max (pointer on the stack) and some pointer on the heap which you point to using pointerToPointer, i.e. the following holds (I dereference `pointerToPointer, which leads to the value stored behind this pointer, which is a pointer to an int):
max == *pointerToPointer
Is there a way to create an initialize a pointer with one instruction?
yes:
int * a = new int(20); //initialized with 20;
How can I create a pointer on the stack?
int myVar = 20;
int* pVar = &myVar; //copied your code snipped It's alright
Your first example
int* max = new int;
*max = 0;
is indeed creating a new int on the heap, and your variable max saves a pointer to that int. If you're going to use this you're going to have to use delete max; when you no longer need it to avoid memory leaks.
The second example
int myVar = 20;
int* pVar = &myVar;
is creating a int on the stack, pVar now is a pointer to the address where the int is saved in the memory. However if you're using this you don't have to delete the pVar because its not on the heap (you didn't use the new keyword).
The main difference between the two variables (created on heap and stack) is that the stack variable is going to get deleted automatically when it leaves the scopes. The scope is defined by curly braces {}:
int* somefnc()
{
int e1
{
int* e2 = new int(0);
int e3 = 0;
} // int e3 gets automatically deleted here
return e2;
} // e1 gets automatically deleted here
// e2 still exists and has to be manually deleted.
One of the advantage of pointers is when dealing with arrays. If you were to make a char array of x elements on the stack you have to know the number of elements at compile time. If you want to make a char array of x elements at runtime with a dynamic number of elements you'd have to use char* ar = new char[x]; and then access it by ar[x-1] = '\n';.
In order to initialise a variable when creating it on heap you can use var x = new var(args);.
you can pass the value as argument to initialize the memory in heap.
int *iptr = new int(20);
it is initialized with value 20;
stack: contains local variables. so when you create a pointer and assign it with local objects. its pointing to variables in stack. we are not creating pointer on heap
.

Does setting an array (int*) to NULL free the memory it occupies?

Say I have an array declared as:
int* array;
and I fill the array with however many integers.
If I later say
array = NULL;
does this free the memory that the numbers in array occupied, or does it just make the array unusable while the memory still lingers?
int* array; is not an array, it's a pointer. You have no array at this point. You can't start doing array[0] = 5; or anything because it doesn't even point at a valid int object, let alone an array of ints.
An array is declared by doing:
int array[5];
This array does have 5 objects ready for you to start assigning to. However, this array must not be deleted. The array was not dynamically allocated.
However, if you were to have done int* array = new int[5];, you would by dynamically allocating an array of 5 ints and getting a pointer to the first element in that array. In this case, you must delete[] array;. If you don't and only set the pointer to NULL or nullptr, you will only leak memory.
If you allocated the memory using new [] (more likely, since the name of the variable is array) or new, this will result in a memory leak.
Setting the pointer to NULL will not release the memory, only reassign the pointer. In other words, you will lose any chance to refer to the previously allocated memory.
Use delete[] to release memory allocated with new[], and delete to release memory allocated with new.
However, consider not using raw pointers and manual memory management at all, they are most often not needed and error-prone. The C++ Standard Library comes with collections and smart pointers that perform memory management under the hood and keep you safe from this kind of mistakes.
When you use the code
int *array;
array = NULL;
you have initialized the pointer. When you assign data to *array
int *array;
array[1] = 3;
you get an undefined behavior, but in most cases an access violation. When you allocate memory before writing and assign NULL to the pointer
int *array;
array = new int[3];
array[0] = 2;
array[2] = 4;
array = NULL;
you get a memory leak. Everything should be fine, when you delete the data:
int *array;
array = new int[3];
array[0] = 2;
array[2] = 4;
delete[] array;
array = NULL;
Setting the array to NULL does not free the memory.
Weather it is usable will depend on the surrounding code and how array is initialized. But you have not provided that information so anything else would be speculation.
Note it is unusual to use pointers in modern C++ code.
You should be looking to use a more appropriate structure. What that is will depend on what your usage us. Based on the name alone array. You should probably be using std::vector<int> (or std::array<int> C++11) or even a plain old C array int array[5].
it will leak the memory and it will only be freed when the process exits.
There is every chance that a segmenation fault may occur.
If you have:
int *array = new int[10];
you need to use
delete [] array;
to free the memory.
Basically follow the rule: Whenever allocating with new XXX deallocate with delete XXXor for array allocation delete [] XXX.
If you just use array = NULL, you only set the pointer to NULL and you will have a memory leak.

Is there a way to expand a dynamic memory array in C++?

Is there a way to expand a dynamic memory array? like this:
int *a = new int[5];
*a = new int[2];
Is this legal?
You cannot expand this type of a dynamic memory array. You can use malloc and realloc though if you need this facility but I would advice against that and suggest including <vector> and using std::vector instead. It has a resize method.
Also, what you described won't compile. The following will:
1: int *a = new int[5];
2: a = new int[2];
The above will allocate two memory blocks, neither of which will be destroyed. Second line will simply assign a new array to the same int *a pointer. When an allocated memory stops being referenced by any pointer, this is called a memory leak. The above code loses any reference to new int[5] and there is no way to free this memory to the operating system.
Although this is not a very practical example, there are multiple ways to resize an array/vector.
As it is usually practical to increase the array size, I will do just this:
{ // C++ vector on the stack (although internally vector uses memory from the heap)
std::vector<int> a(1024);
// do smth
a.resize(4096); // note: this does not always reallocate
// do smth else
}
{ // C++ everything on the heap
std::vector<int> *a = new std::vector<int>(1024);
// do smth
a->resize(4096); // note: this does not always reallocate
// do smth else
delete a;
}
{ // C style
int *a = (int*)malloc(1024*sizeof(int));
// do smth
a = realloc(a, 4096*sizeof(int));
// do smth else
free(a);
}
It is worth to note that realloc does not do anything smart. All it does is:
Allocate new memory block malloc
Copy data from old memory block to new memory block memcpy
Free old memory block free
Return new memory block
You can certainly expand an array, but you need to take care of copying the contents and of freeing the old array (your code, apart from being incorrect syntax, shrinks the array, btw.).
Which is exactly how std::vector works, just you don't have to care.
So basically, having int *a already allocated, what needs to happen is something like:
{
std::unique_ptr<int[]> d(a);
a = new int[desired_new_size];
for(unsigned int i = 0; i < min_old_size_and_new_size; ++i)
a[i] = d[i];
}
Note that strictly speaking "expanding" never really expands the array, but replaces it with another bigger one (that is true for any containers offering the same functionality too). But this is transparent to any code using the pointer later, nobody will know.
You should never use realloc (or any other C memory allocation functions) in combination with memory allocated or freed by operator new and delete (or new[] and delete[]) as pointed out above.
This may work (and usually will), but it's conceptually wrong, and it's pure luck (unknown implementation detail) if it does not crash.

C++ filling an array with numbers then returning a pointer to it

Ive been faced with a problem recently that I can't think of a good way to solve. I'm using a case structure to attempt to set attributes to a "character" that will be passed to an object constructor.
Example:
//note this is inside a function with a return type of int*
int selection;
cin >> selection;
int * iPtr;
switch(selection){
case 1:{
int anArray[6] = {8,5,2,4,250,100} // str, dex, int, luck, hp, mp
iPtr = anArray;
return iPtr;
}
//more cases and such below
The issue that I'm having is that when I return my pointer it seems to be filled with a good amount of junk, rather than the information, rather than the information that I would be expecting it to hold. Is that because the array gets destroyed at the end of the scope? If so what should I do to make this work out how I'm hoping for it to (getting a pointer with the values that I want).
Thanks!
Yes - anArray is declared on the stack. When the function exits, its stack frame is reclaimed, so it's no longer valid to refer to that memory. If you want the array to persist, allocate it on the heap instead:
int* anArray = new int[6]; // and initialize
return anArray;
Just remember to clean it up later at some point with the corresonding delete[].
EDIT
You should prefer to use something that automatically manages resources for you, like in Praetorian's answer, so that you don't accidentally leak memory.
Yes, the array you've declared is indeed local to the function and no longer exists once the function exits. You can dynamically allocate an array using new and then have the caller delete[] the memory (but don't do this!), or modify your function to return an std::unique_ptr instead of a raw pointer.
unique_ptr<int[]> anArray (new int[6]);
// do initialization
return anArray;
Now, the caller doesn't have to worry about freeing memory allocated by the function.
EDIT:
There are a couple of different ways to perform initialization of the unique_ptr.
anArray[0] = 8;
anArray[1] = 5;
// etc ...
OR
int init[6] = {8,5,2,4,250,100};
std::copy( &init[0], &init[0] + 6, &anArray[0] );
Yes, it's because the local array is overwritten as the program runs. You can either declare the array static in the method (which would be a good idea for a fixed array like this), declare it at global scope, or allocate an array with new to return. The last alternative gives you the opportunity to have a different array returned for each call, but remember to deallocate the arrays after use.
In C++, the best answer is not to return a pointer. Instead, use a proper object instead of a C array or manually allocated memory and return this object:
std::vector<int> f() {
std::vector<int> array;
// fill array
return array;
}
Using new int[x] (or whatever) is really, really deprecated in modern C++ code and is only deemed acceptable under very special circumstances. If you use it in normal code, this is a very obvious place for improvement. The same goes for other uses of manually managed memory. The whole strength of C++ lies in the fact that you don’t have to manage your own memory, thus avoiding a multitude of hard to track bugs.
Yes, it is because the array you created is created on the stack, and when you return, the part of the stack that you were at is overwritten (presumably by a debug process).
To avoid this, you would write
int* anArray = new int[6];
// fill the array
return anArray;
In this case, you will also have to delete the returned result when you are finished with it, such as in
int* dataArray = getTheArray();
// Use the dataArray
delete [] dataArray;
Allocate array on the heap
int* anArray = new int[6];
You will have to delete it manually:
delete[] iPtr;