I have allocated and array of Objects
Objects *array = new Objects[N];
How should I delete this array?
Just
delete[] array;
or with iterating over the array's elements?
for(int i=0;i<N;i++)
delete array[i];
delete[];
Thanks
UPDATE:
I changed loop body as
delete &array[i];
to force the code to compile.
Every use of new should be balanced by a delete, and every use of new[] should be balanced by delete[].
for(int i=0;i<N;i++)
delete array[i];
delete[] array;
That would be appropriate only if you initialized the array as:
Objects **array = new Objects*[N];
for (int i = 0; i < N; i++) {
array[i] = new Object;
}
The fact that your original code gave you a compilation error is a strong hint that you're doing something wrong.
BTW, obligatory: avoid allocating arrays with new[]; use std::vector instead, and then its destructor will take care of cleanup for you. Additionally it will be exception-safe by not leaking memory if exceptions are thrown.
Just delete[] array is sufficient. It is guaranteed that each element of the array is deleted when you delete an array using delete[] operator.
As a general rule you should delete/delete[] exactly those things that you allocated with new/new[]. In this case you have one allocation with new[], so you should use one call to delete[] to free that allocated thing again.
That the deletes in the for-loop won't compile is also a good indication that they are not the right way to do it.
Not only is
delete [] array;
enough, but if you do
for(int i=0;i<N;i++)
delete &array[i];
delete[] array;
you'll be causing undefined behavior, because
delete &array[i];
will be deleting things that weren't returned by a new operation.
Not to mention that the subsequent delete[] array; will call the destructor for all the objects that just had destructors called in the loop.
So don't do that.
delete [] array
is enough.
Related
So, I have dynamically assigned memory to a 2D array:
int **paMatrix = new int*[r];
for(int i=0; i<r; i++)
paMatrix[i] = new int[c];
Assume that my code has already defined r and c. Now I want to free the memory again. If paMatrix was single-indexed, the delete[] paMatrix; would be enough. Is it also enough in this case, or do I have to write
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?
In general, you need to match every new with a delete so if, as here, you're juggling a whole array of raw pointers, you will indeed need to delete each in turn.
This can be a serious hassle if the code between new and delete isn't straightforward, and almost impossible to ensure if it might throw exceptions. For that reason, you should always use RAII types such as containers and smart pointers to manage dynamic resources. In this case, vector<vector<int>> might be an appropriate choice.
I guess the real question is "What does delete and delete[] really do behind the scene?"
If the object type has a non-trivial destructor, it calls that destructor on each object before deallocating the memory. Thus RAII types will automatically release whatever resource they manage through their destructor; but raw pointers don't have destructors, so deleting them will not free any memory that they point to.
As said, in c++ one rarely has more then one indirection through pointers. In a matter of fact, in c++ pointers are avoided whenever possible.
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?
One way would be :
int *paMatrix = new int[r*c];
but then you need to play with indexes.
Another solution (without pointers) without even one delete statement is to use std::vector :
std::vector< std::vector< int > > paMatrix( r, std::vector< int >( c, 0 ) );
You need
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
There's no way around, except smart pointers etc.
As described in the other answers here, you need to match calls to new with calls to delete.
However if you were willing to change your conception of a 2d array, you can simplify it considerably. For example if it truly a matrix of r x c size you could allocate it as a single array of r*c in size:
int* paMatrix = new int[r*c];
Then you would be able to delete it in a single step.
The tradeoff would be having to index the array using something like paArray[x+c*y] instead of the more natural paArray[x][y].
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)
so I have a pointer that points to an array of pointers!
int **matrixPtr;
matrixPtr = new int*[5];
for(i=0; i<5; ++i){
matrixPtr[i]= new int[5];
}
I'm wondering if this is the proper way to free up the memory!
for(i=0; i<5; ++i){
delete [] matrixPtr[i];
}
delete [] matrixPtr;
Thanks!
No problem. It's right!
You deallocated in the reverse order that you allocated!
I don't even think there's another way to do that.
Yes and no. Yes, it's the right way to manually free the memory if you have to allocate it manually like you did.
But no, you should avoid manual allocation and deallocation of memory. If you are stuck with C++03 and without any smart pointers, you should use a vector of vectors. In C++11 you have more options, namely smart pointers and std::array, the latter only if you know the size of the inner or outer dimension or both at compiletime. In C++14 std::dynarray could become an option, too.
I have an abstract Base class and Derived class.
int main ()
{
Base *arrayPtr[3];
for (int i = 0; i < 3; i++)
{
arrayPtr[i] = new Derived();
}
//some functions here
delete[] arrayPtr;
return 0;
}
I'm not sure how to use the delete operator. If I delete array of base class pointers as shown above, will this call derived class objects destructors and clean the memory?
You have to iterate over the elements of your array, delete each of them. Then call delete [] on the array if it has been allocated dynamically using new[].
In your sample code, the array is allocated on the stack so you must not call delete [] on it.
Also make sure your Base class has a virtual destructor.
Reference: When should my destructor be virtual.
No, you have to explicitly delete each item in the array:
for (int i = 0; i < 3; ++i)
{
delete arrayPtr[i];
}
You should instead do:
for ( int = i; i < 3; i++ )
{
delete arrayPtr[i];
}
And you shouldn't do delete[] arrayPtr; as you're trying to free/delete a stack allocated arrayPtr.
Another thing to consider is using a std::vector of pointers instead of an array. And if you're using a compiler that implements TR1, you could also use a std::vector of std::tr1::shared_ptr instead of raw pointers, and than you wouldn't need to worry about deleting those objects yourself.
Example:
{
std::vector< std::tr1::shared_ptr<Base> > objects;
for (int i=0; i < 3; ++i)
{
objects.push_back(std::tr1::shared_ptr<Base>(new Derived()));
}
} // here, once "objects" exit scope, all of your Derived objects are nicely deleted
You have to delete the members of the array individually. You must also make sure that your base class has a virtual destructor. You might also want to consider making it an array (or better still a std::vector) of smart pointers, such as boost::shared_ptr.
No, you can not do that. As others suggested you have to go through each item and delete it. It's a very simple rule to remember. If you allocated using new then use delete, and if you had used new[] then use delete[]
Notice what's absent:
int main() {
boost::ptr_vector<Base> v;
for (int i = 0; i < 3; i++) v.push_back(new Derived());
// some functions here, using v[0] through v[2]
}
Check Boost's pointer containers out.
Operator delete must match operator new on that pointer, if it was allocated with new[], you must call delete[] and vice versa;
int* pInt = new int;
delete pInt; OK
delete [] pInt; WRONG
int[] pIntArr = new int[3];
delete [] pIntArr; OK
delete pIntArr; WRONG
In your case there is something else wrong - you are trying to delete that was allocated on the stack. That wouldn't work.
You must delete each pointer individually in this particular case.
What you have there is undefined behaviour -- a bug. Each call to new needs to be matched with a delete; each call to new[] needs to be matched with a delete[]. The two are separate and can't be mixed.
In the code you posted, you have an array of pointers to Base allocated on the stack. You're then calling delete[] on an array allocated on the stack -- you can't do that. You can only delete[] an array allocated on the heap with new[].
You need a call to delete for each element allocated with new -- or preferably, look into using a container class, such as std::vector, instead of using an array.
Make sure Base has a virtual destructor. Then like fretje outlined, delete each element in the array, then delete the array.
You should be using std::vector for the array. That said, you should really be using a container made for this sort of thing. (So you don't accidentally fail to delete all the elements, which will definitely be the case if an exception gets thrown!) Boost has such a library.
You're mixing paradigms -- The array delete operator is designed to free memory allocated by the array new operator, but you're allocating your array on the stack as an array of pointers and then allocating an object for each array member. In your code, you need to iterate through the array.
To use the array new operator, you'd declare like this:
Base *array;
array = new Base[3];
/* do stuff */
delete[] array;
This allocates a contiguous memory area for the three objects -- note that you've got an array of Base objects, not an array of pointers to Base objects.
No, this doesn't quite do what you want.
There are two points to watch out for here:
The syntax delete[] arrayPtr is used if you dynamically allocate the array, like this:
arrayPtr = new (Base *)[mylength];
In your case, however, you have a statically allocated array, so there is no need to delete it. You do, however, need to delete the individual elements in the array:
for ( int = i; i < 3; i++ )
delete arrayPtr[i];
The second point you need to take care of is to make the destructor of the class Base virtual:
class Base
{
virtual ~Base();
/* ... */
};
This ensures that when you call delete on a Base * that is actually pointing to a Derived, the destructor of Derived is called, not just the destructor of Base.
Why this code does not cause memory leaks?
int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
std::auto_ptr<char> buffer(new char[sizeBig]);
}
WinXP sp2, Compiler : BCB.05.03
Because you're (un)lucky. auto_ptr calls delete, not delete []. This is undefined behavior.
Try doing something like this and see if you get as lucky:
struct Foo
{
char *bar;
Foo(void) : bar(new char[100]) { }
~Foo(void) { delete [] bar; }
}
int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
std::auto_ptr<Foo> buffer(new Foo[sizeBig]);
}
The idea here is that your destructor for Foo will not be called.
The reason is something like this: When you say delete[] p, the implementation of delete[] is suppose to go to each element in the array, call its destructor, then free the memory pointed to by p. Similarly, delete p is suppose to call the destructor on p, then free the memory.
char's don't have a destructor, so it's just going to delete the memory pointed to by p. In my code above, it is not going to destruct each element in the array (because it's not calling delete[]), so some Foo's will leave their local bar variable un-deleted.
The auto_ptr will only live for the duration of the loop iteration and will release the object connected to it on iteration completion.
The compiler can see that in this case new[] can allocate space in the same way as new - without storing the number of elements anywhere since there's no need to call trivial char destructors - and that's why later when delete is called by the auto_ptr's destructor instead of delete[] it causes no problems since the memory block has actually been allocated in the new's way and that allocation can be paired with delete.
This is an example of a thing not to do. It's up to the compiler to decide whether to replace new[] with new. Using delete instead of delete[] and vice versa is undefined behaviour.
See Why would you write something like this? (intentionally not using delete [] on an array) for discussion of delete vs delete[].