In simple 1D array:
node *nodes = new node[MAX_NODES];
Deleting by:
delete [] nodes;
Deletes all the nodes allocated in the array.
But in this case:
float (*buildingArray)[3] = new float[10][3];
Does this statement make buildingArray a single dimension array of 3 float pointers? And this is the deallocation line:
delete[] buildingArray;
Does the above deallocation delete the array, but I am doubtful about whether it will delete its references?
Does the above de-allocation delete the array?
Yes it does.
Simply follow the rule:
You need to call delete or delete [] as many times you called new or new [] respectively.
If you had an array of pointers where each index was allocated dynamic memory, you would need to explicitly loop through it and deallocate each array element explicitly.
On a side note you are much better off using a std::vector or std::array rather than dynamically allocated array.
Yes it does. The explanation is because there is no information in memory about how much dimensions your array has.
If you have a 3*4 items array, it's exactly the same as a 12 items array. It's just the way you address the specific elements (which are stored in a line after line fashion) that changes.
So delete[] will work perfectly.
But using new and delete operators is not so common these days with smart pointers, unless you really have a good reason to control allocation yourself.
new float[10][3] allocates an array of 10 arrays of 3 floats and returns a pointer to the first element (which is an array of 3 floats).
Calling delete[] on this pointer causes the whole array to be deleted.
The only difference between the two cases is that in the first case, the type of the values stored in the dynamically allocated array is float and in the second case the type is float[3].
Related
This question is similar to Problem with delete[], how to partially delete the memory?
I understand that deleting an array after incrementing its pointer is not possible as it loses the track of how many bytes to clean. But, I am not able to understand why one-by-one delete/deallocation of a dynamic array doesn't work either.
int main()
{
int n = 5;
int *p = new int[n];
for(int i=0;i<n;++i){
delete &p[i];
}
}
I believe this should work, but in clang 12.0 it fails with the invalid pointer error. Can anyone explain why?
An array is a contiguous object in memory of a specific size. It is one object where you can place your data in and therefore you can only free/delete it as one object.
You are thinking that an array is a list of multiple objects, but that's not true. That would be true for something like a linked list, where you allocate individual objects and link them together.
You allocated one object of the type int[n] (one extent of memory for an array) using the operator new
int *p = new int[n];
Elements of the array were not allocated dynamically separately.
So to delete it you just need to write
delete []p;
If for example you allocated an array of pointers like
int **p = new int *[n];
and then for each pointer of the array you allocated an object of the type int like
for ( int i = 0;i < n;++i )
{
p[i] = new int( i );
}
then to delete all the allocated objects you need to write
for ( int i = 0; i < n; ++i )
{
delete p[i];
}
delete []p;
That is the number of calling of the operator delete or delete [] one to one corresponds to the number of calling operator new or new [].
One new always goes with one delete. Just as that.
In detail, when we request an array using new, what we actually do is to get a pointer that controls a contiguous & fixed block on the memory. Whatever we do with that array, we do it through that pointer and this pointer associates strictly with the array itself.
Furthermore, let's assume that you were able to delete an elemnent in the middle of that array. After the deletion, that array would fall apart and they are not contiguous anymore! By then, an array would not really be an array!
Because of that, we can not 'chop off' an array into separate pieces. We must always treat an array as one thing, not distinctive elements scattered around the memory.
Greatly simplyfyinh: in most systems memory is allocated in logical blocks which are described by the starting pointer of the allocated block.
So if you allocate an array:
int* array = new int[100];
OS stores the information of that allocation as a pair (simplifying) (block_begin, size) -> (value of array ptr, 100)
Thus when you deallocate the memory you don't need to specify how much memory you allocated i.e:
// you use
delete[] array; // won't go into detail why you do delete[] instead of delete - mostly it is due to C++ way of handling destruction of objects
// instead of
delete[100] array;
In fact in bare C you would do this with:
int* array = malloc(100 * sizeof(int))
[...]
free(array)
So in most OS'es it is not possible due to the way they are implemented.
However theoretically allocating large chunk of memory in fact allocate many smaller blocks which could be deallocated this way, but still it would deallocate smaller blocks at a time not one-by-one.
All of new or new[] and even C's malloc do exactly the same in respect to memory: requesting a fix block of memory from the operating system.
You cannot split up this block of memory and return it partially to the operating system, that's simply not supported, thus you cannot delete a single element from the array either. Only all or none…
If you need to remove an element from an array all you can do is copy the subsequent elements one position towards front, overwriting the element to delete and additionally remember how many elements actually are valid – the elements at the end of the array stay alive!
If these need to be destructed immediately you might call the destructor explicitly – and then assure that it isn't called again on an already destructed element when delete[]ing the array (otherwise undefined behaviour!) – ending in not calling new[] and delete[] at all but instead malloc, placement new for each element, std::launder any pointer to any element created that way and finally explicitly calling the constructor when needed.
Sounds like much of a hassle, doesn't it? Well, there's std::vector doing all this stuff for you! You should this one it instead…
Side note: You could get similar behaviour if you use an array of pointers; you then can – and need to – maintain (i.e. control its lifetime) each object individually. Further disadvantages are an additional level of pointer indirection whenever you access the array members and the array members indeed being scattered around the memory (though this can turn into an advantage if you need to move objects around your array and copying/moving objects is expensive – still you would to prefer a std::vector, of pointers this time, though; insertions, deletions and managing the pointer array itself, among others, get much safer and much less complicated).
I am confused about how to create a dynamic defined array:
int *array = new int[n];
I have no idea what this is doing. I can tell it's creating a pointer named array that's pointing to a new object/array int? Would someone care to explain?
new allocates an amount of memory needed to store the object/array that you request. In this case n numbers of int.
The pointer will then store the address to this block of memory.
But be careful, this allocated block of memory will not be freed until you tell it so by writing
delete [] array;
int *array = new int[n];
It declares a pointer to a dynamic array of type int and size n.
A little more detailed answer: new allocates memory of size equal to sizeof(int) * n bytes and return the memory which is stored by the variable array. Also, since the memory is dynamically allocated using new, you should deallocate it manually by writing (when you don't need anymore, of course):
delete []array;
Otherwise, your program will leak memory of at least sizeof(int) * n bytes (possibly more, depending on the allocation strategy used by the implementation).
The statement basically does the following:
Creates a integer array of 'n' elements
Allocates the memory in HEAP memory of the process as you are using new operator to create the pointer
Returns a valid address (if the memory allocation for the required size if available at the point of execution of this statement)
It allocates space on the heap equal to an integer array of size N,
and returns a pointer to it, which is assigned to int* type pointer called "array"
It allocates that much space according to the value of n and pointer will point to the array i.e the 1st element of array
int *array = new int[n];
The new operator is allocating space for a block of n integers and assigning the memory address of that block to the int* variable array.
The general form of new as it applies to one-dimensional arrays appears as follows:
array_var = new Type[desired_size];
In C/C++, pointers and arrays are (almost) equivalent.
int *a; a[0]; will return *a, and a[1]; will return *(a + 1)
But array can't change the pointer it points to while pointer can.
new int[n] will allocate some spaces for the "array"
As of C++11, the memory-safe way to do this (still using a similar construction) is with std::unique_ptr:
std::unique_ptr<int[]> array(new int[n]);
This creates a smart pointer to a memory block large enough for n integers that automatically deletes itself when it goes out of scope. This automatic clean-up is important because it avoids the scenario where your code quits early and never reaches your delete [] array; statement.
Another (probably preferred) option would be to use std::vector if you need an array capable of dynamic resizing. This is good when you need an unknown amount of space, but it has some disadvantages (non-constant time to add/delete an element). You could create an array and add elements to it with something like:
std::vector<int> array;
array.push_back(1); // adds 1 to end of array
array.push_back(2); // adds 2 to end of array
// array now contains elements [1, 2]
I understand that we use this when we need to give a pointer to an array of pointers in the dynamic memory but what I don't understand is that how this works in the stack.
Does this make an array of pointers in the stack too that is pointing to the array of pointers in the heap or does it make a single pointer in the stack that is pointing to the array of pointers in the heap? if yes, then what is the difference between
int **p = new int*[100]
and
int *p = new int[100]
Thanks in advance. I have been trying to understand this for a long time now and have read a lot of documentation online but I still don't understand this.
int **p declares a pointer on the stack which points to pointer(s) on the heap. Each of that pointer(s) point to an integer or array of integers on the heap.
This:
int **p = new int*[100];
means that you declared a pointer on the stack and initialized it so that it points to an array of 100 pointers on heap. For now each of that 100 pointers point nowhere. By "nowhere" I mean that they point neither to a valid chunk of memory, nor they are nullptrs. They are not initialized, thus they contain some garbage value which was in the memory before the pointers were allocated. You should assign something sensible to them in a loop before usage. Note that p[0] - p[99] pointers are not guaranteed to point to adjacent regions of memory if you assign return values of new to them. For example, if you allocate memory for each of them as p[i] = new int[200];, p[0][201] will not reference p[1][2], but will lead to an undefined behavior.
And this:
int *p = new int[100];
is a pointer on the stack which points to an array of 100 integers on the heap.
Don't worry, pointers and arrays in C are always a source of confusion. In general, when you declare an array of, say type int, you create a pointer of type int that points to the first element in a contiguous block of memory that will store ints. For example, if I have a simple array of ints using int *p_to_intarr = new int[3], I get this:
+++++++ <--------- p_to_intarr
| int |
+++++++
| int |
+++++++
| int |
+++++++
In general, if I want an array of type T, I create a pointer to type T like T *ptr_to_Tarr = new T[3].
So what if I want an array of array of ints? Lets just replace the T in with the type of an "array of ints" and this will give us an array of "array of ints". Well we just say in our first example that the type of an array of ints in int *, and so an array of array of ints would be: int* *ptr_to_arrayofintarr = new int*[3]. Note we just replaced the T with int star. This is often written more neatly as int **ptr_to_arrayofintarr = new int*[3].
So int **p could be a pointer to a 2d array. It could also be a reference to a 1d array; depends on the specific case :)
The new expression evaluates to a pointer of some type, pointing to memory that has been allocated in the free store (essentially the heap) but not necessarily in the free store. (It can still be in the free store depending on the context; for instance, consider an initialization-list in a constructor for an object being allocated in the free store.)
The object(s) initialized by new is/are of course in the free store.
In the assignment statements you've shown, you can see the type of the pointer returned by new on the left side of the equals sign, and the type of the free store object(s) to the right of the new. Thus the only object that is locally evaluated (i.e. might be on the stack) is, in the first case, a pointer-to-pointer-to-int, and in the second case, a pointer-to-int. The objects in free space are an array of pointers-to-ints in the first case and a simple array of ints in the second.
Note that just because the array in the first assignment consists of pointers doesn't mean that the pointers themselves actually point to anything yet; new does not magically recursively allocate free space for objects to be targeted by any pointers in an array it creates. (This wouldn't make much sense anyway.)
The ** means that you have a pointer to pointers. In more practical terms, it means you have a two-dimensional array.
Since each element of the array is also a pointer, you need to initialize those pointers as well:
for (int i = 0; i < 100; ++i)
p[i] = new int[200];
This initializes a 100x200 array. You can access the bottom-right corner with p[99][199].
When it's time to delete the pointer you have to reverse the process:
for (int i = 0; i < 100; ++i)
delete [] p[i];
delete [] p;
This question already has answers here:
delete vs delete[] operators in C++
(7 answers)
Closed 9 years ago.
What is the difference between doing:
int* I = new int[100];
for (int J = 0; J < 100; ++J)
{
delete I++;
}
//and
int* I = new int[100];
delete[] I;
I know that the first is wrong. I know how to use delete[] vs. delete correctly.
I just want to know why these are any different. Like figure out the real difference between delete[] and delete in a loop. So what is the difference?
Both versions of new and delete each have two tasks: allocation/deallocation and construction/destruction.
new will allocate memory and call a constructor.
delete will call a deconstructor and deallocate memory.
new [] allocates single chunk of memory and then calls a constructor possibly several times.
delete [] calls a deconstructor possibly several times and then deallocates a single chunk of memory.
So using delete multiple times means deallocating multiple chunks of memory whereas using delete[] will deallocate a single chunk of memory; using delete multiple times is not equivalent to using delete [].
The difference is that in the first, you're deleting pointers that you didn't get back from new.
There's no point of comparision
Use deletes for all news
and delete []s for all new []s
The first one simply deletes pointer not coming from new
When you use new Foo[n], you're making a single allocation for a chunk of memory big enough to hold an array of n contiguous elements of type Foo. This is not the same as allocating n contiguous chunks of memory, one for each Foo.
From the point of view of the memory allocator, it's really only one big allocation. When you do delete array or delete (array + 42), the memory allocator is basically asked to delete the part of the big allocation that holds a specific item, which it cannot do. It's like trying to free up a single member of a new'ed object by doing delete (&(new Foo())->bar) - what happens to the rest of the object?
Even on a single-element array, delete array will not work because the allocator uses different bookkeeping logic for arrays and single objects (for example, storing the number of elements in the array). So you really do have to use delete[] with new[] and delete with new.
This is declaring an array of integers:
int* I = new int[100];
This is iterating through an array of integers and trying to delete them:
for (int J = 0; J < 100; ++J)
{
delete I++; // bad
}
This is deleting the array of integers:
delete [] I; // correct
Since you allocated the array with [], you deallocate it with []. You do not deallocate memory you allocated with [] without [].
The difference between delete and delete[] is that delete will invoke the destructor of one object, while delete[] will invoke the destructor of every object in the array. In the case of ints, the difference isn't noticable, but if you anything of consequence in your destructor, you'll problems since you won't be properly destroying all of your objects.
That said, you still shouldn't use delete instead of delete[] for simple types since the compiled code may be different for the two operators (for example, delete[] may be expecting an integer to be stored somewhere adjacent to the array to indicate the number of objects to delete). So, the general rule is if you used new, always use delete, and if you used new[], always use delete[].
The first example yields undefined behavior, because a plain delete expression (as opposed to delete[]) can only be applied to an operand that is either:
a null pointer value
a pointer to a non-array object created by a previous new-expression
or a pointer to a subobject
Calling delete on an individual element of an array allocated with new[] does not fall in either of these categories, because the elements of your array are non-array objects that have NOT been created with an individual new expression.
(C++ standard 5.3.5)
Why is there a delete[]? From my understanding its to behave differently for arrays. However, why does it really exist? There's only free in C and no free_array. Also in syntax the only difference between delete var and delete []var is the [] which has no params (I'm not telling the length of the array).
So why does delete[] really exist? I know someone will say you can overload delete and delete[] (at least i think that is possible) but lets say we are not overloading it. Why does it exist?
Typically, for non-POD classes, a delete[] expression must call destructors on a variable number of class instances that cannot be determined at compile time. The compiler typically has to implement some run time "magic" that can be used to determine the correct number of objects to destroy.
A delete expression doesn't have to worry about this, it simply has to destroy the one object that the supplied pointer is pointing to. Because of this, it can have a more efficient implementation.
By splitting up delete and delete[], delete can be implemented without the overhead needed to correctly implement delete[] as well.
If you delete an array, only first object's destructor will be called. delete[] calls destructors of all objects in array and frees array's memory.
Assume delete[] didn't exist, write the code for deleting the array vs deleting only the first element in the array.
delete array; // Deletes first element, oops
delete &array; // Deletes first element, oops
delete &array[0]; // Deletes first element
A pointer to an array being an alias for a pointer to the first element of the array is of course an old C "feature".
Consider:
int* a = new int[25];
int* b = a;
delete b; // only deletes the first element
The C++ compiler has no idea whether b points to an array or a single element. Calling delete on an array will only delete the first element.