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.
Related
I am trying to implement a self-made vector class with dynamic length. The idea is to use a pointer and dynamically allocated space as follows.
template<class T>
class myVector
{
int size;
T* array;
public:
myVector(int n): size(n), array(new T[n]){}
~myVector(){delete[] array;}
T pop();
...
}
and if I need to push, I create a new object with a new pointer pointing to newly allocated space and copy the whole whing. Now I am stuck on the pop part because I don't know how to free the unused space after pop() is called.
Is it okay if I use delete in pop() like this
T pop()
{
T = *(array+size-1);
delete array+size-1;
return T;
}
But if I do this then when the destructor is called the popped place gets deleted twice, and I think something could go wrong with that. And I know I can wait until the whole array is empty before deleting, but it might happen that a very large array is allocated at first and gets popped a lot while the program's running, which could lead to a large number of unused spaces if I don't free them in the middle.
My questions:
(1) What happens if I were to write delete in pop()?
(2) What can I do? (preferably with delele only)
Your code is severely flawed.
Firstly, any new T[N] must be deleted with a delete[]. So your destructor needs to use delete[], not delete.
Then, you cannot use delete to pop single elements from your buffer. That is undefined behavior (security risk) because the elements have not been allocated with new.
The way a real vector handles this, is to allocate a buffer of char on the heap, and then manually invoke the constructors and destructors of T in the buffer, by using placement new and explicit destructor calls.
You must delete what you new and delete[] what you new[] and nothing else. You cannot delete individual elements from a dynamically allocated array, only the whole thing. Your current destructor has Undefined Behavior because you delete something that you created with new[].
1) Undefined Behavior happens. Don't do it.
2) Delete the whole array and allocate a new one with one less element. Since that's terrible for performance (adding N elements has O(N^2) runtime) you should look into the size + capacity thing that std::vector does.
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)
int* func()
{
int* i=new int[1];
//do something
return i;
}
void funcc()
{
int* tmp=func();
//delete allocated memory after use
delete tmp;
}
should delete working as described in the second function be a correct use ?
I think I didn't allocate memory to it by new ? new was used in the first, to be sure.
It should be delete [] tmp; because you're doing array new, but otherwise, it's correct.
As others have stated, you should use delete[] to delete arrays, not delete.
But, if you're asking whether it's okay to delete tmp because the memory it points to wasn't allocated with new, then your premise is incorrect.
It was allocated with new. The address of the memory that you allocate within the function for i is passed back to be stored in tmp, so it does point to memory that was allocated by new.
You're correct that i itself is out of scope at that point but memory allocated by new survives the scope change on exit from the function. And, since you're storing its location into tmp, you still have access to it.
Hence the deletion (once you make it an array deletion with []) is quite valid.
This is Undefined Behaviourâ„¢. You can only use delete if you used new. If you used new[], you MUST delete[] it. More than that, this is hideously unsafe code- you need a smart pointer.
No. new T[] should match delete []t. And new T should match delete t. Otherwise, your code would invoke undefined bevavior.
And it doesn't matter if you do delete []tmp outside the function. Its okay to do so. All that you need to keep in mind that the form of delete.
My spidey-senses tell me that you're wondering whether the dynamically-allocated int that you create in func is the same one that you attempt to delete in funcc.
The answer is: yes. Although you don't use strictly the same pointer variable, both pointers point to the same object.
However, please remember to use delete[] (with the []) when you used new[] (with the []). Your code is broken until you fix this.
Also, try to avoid newing in one place and deleteing in another. Perhaps consider a std::vector instead, which is far less error-prone.
I saw an example of using the function: delete in cpp and I didn't completely understand it.
the code is:
class Name {
const char* s;
//...
};
class Table {
Name* p;
size_t sz;
public:
Table(size_t s = 15){p = new Name[sz = s]; }
~Table { delete[] p; }
};
What is the exact action of the command: delete[] p;?
I think the aim was to delete all the pointers in the container Table.
The brackets in delete[] give me a clue that it deletes an array of pointers to Name but the size of the array is not specified, so how does the destructor "know" how many pointers to delete?
delete isn't a function, it's an operator.
A delete expression using [] destroys objects created with new ... [] and releases the associated memory. delete[] must be used for pointers returned by new ... []; non-array delete only on pointers returned by non-array new. Using the non-matching delete form is always incorrect.
The delete expression in ~Table() (missing () in your code) will destroy the dynamically created array of Name objects ensuring that the Name destructor is called for each member of the array.
It is up the the implementation to implement some mechanism of recording the number of elements in arrays allocated with new ... [] the programmer doesn't have to worry about this.
In many implementations, where the array elements have non-trivial destructors, a new[] expression will allocate extra space to record the element count before the space for all the array members. This hidden count is then looked up when delete[] is used to ensure the correct number of destructors are called. This is just an implementation detail, though, other implementations are possible.
In short, delete[] knows the size of the array it is deleting because it is required to.
Because the C++ language standard states that it must know.
So when you allocate an array, it is up to the system to store the size somewhere where delete[] can find it.
One option is to allocate a few bytes more than needed. Use the first bytes to specify the size, and then instead of returning a pointer to the first allocated byte, return a pointer to the first byte past the size field.
Then delete[] just has to subtract a few bytes from the pointer in order to find the size.
Another option could be to have a global map<void*, int>, where the key is the pointer to a memory allocation, and the value is the size of that allocation. There are plenty of other ways in which delete[] can find out the size. The C++ standard doesn't specify which one to use. It just says that delete[] must know the size, and leaves it up to the implementers to figure out how to pull it off.
I have a struct like this:
class Items
{
private:
struct item
{
unsigned int a, b, c;
};
item* items[MAX_ITEMS];
}
Say I wanted to 'delete' an item, like so:
items[5] = NULL;
And I created a new item on that same spot later:
items[5] = new item;
Would I still need to call delete[] to clean this up? Or won't this be needed since bounds of array items[] are known before compiling?
Is setting that pointer to NULL valid or should I be calling delete there?
You need to call delete before setting it to NULL. (Setting it to NULL isn't required, it just helps reduce bugs if you accidentally try to dereference the pointer after deleting it.)
Remember that every time you use new, you will need to use delete later on the same pointer. Never use one without the other.
Also, new [] and delete [] go together in the same way, but you should never mix new [] with delete or new with delete []. In your example, since you created the object with new (rather than new [] which would create an array of objects) you must delete the object with delete (rather than delete []).
As Kluge pointed out, you'd leak the object at index 5 like that. But this one really sounds like you shouldn't do this manually but use a container class inside Item. If you don't actually need to store these item objects as pointers, use std::vector<item> instead of that array of MAX_ITEMS pointers. You can always insert or erase vector elements in the middle as well if you need to.
In case you need to store the objects as pointers (usually if struct item is actually polymorphic, unlike in your example), you can use boost::ptr_vector<item> from Boost.PtrContainer instead.
Example:
class Items {
private:
struct item {
unsigned int a, b, c;
};
std::vector<item> items;
}
if (items.size() > 5) // (just to ensure there is an element at that position)
items.erase(items.begin() + 5); // no need to use operator delete at all
To delete an item use:
delete items[5];
after deleting the item it is advisable to set the deleted pointer to NULL, so you won't have an error if you later delete it again by mistake.
items[5] = NULL
Say I wanted to 'delete' an item, like so:
items[5] = NULL;
I know little Visual Basic, but that smells like a Visual Basic programming idiom, since "Set a = None" (or Null, I'm not sure) would delete the object pointed by a (or rather decrement its reference count, for COM objects).
As somebody else noted, you should use either:
delete items[5];
items[5] = newContent;
or:
delete items[5];
items[5] = NULL;
After delete[5], the only possible use of the pointer stored in items[5] is causing you trouble. What's worse is that it might happen to work at the beginning, and start failing only when you allocate something else over the space previously used by *items[5]. Those are the causes which make C/C++ programming "interesting", i.e. really annoying (even for who likes C like me).
Writing just delete items[5]; saves what can be an useless write, but that's a premature optimization.
Just to be clear: you refer to calling "delete[]". I think you mean delete.
I mention this because C++ has two separate operators, operator delete and operator delete[]. The latter is used for deleting arrays of objects allocated with operator new[], and does not apply in this case. You have an array of pointers to objects, which you must have initialised with repeated calls to operator new rather than a single call to operator new[].
All I'm really trying to say is: your use of delete[] is confusing and ambiguous; change it to delete.
There are a few, related, questions here:
According to the code you posted, the array itself is not allocated on the heap unless the struct is, so you don't need to delete[] the array. If you created the array with new[] you would have to delete[] it.
The code posted doesn't say how the objects being pointed to from the array are allocated. If you allocate those objects on the stack you must not delete them (then again, this is highly unlikely because your pointers will become invalid when the objects they point to fall out of scope). If you allocated them on the heap (with new) then you must delete them when they fall out of scope.
As others have already suggested, life is much easier if you use a container -- especially an STL container -- and smart pointers -- which for now means pointers out of Boost.
C++ isn't my strong suit, but I'm pretty sure you'd be leaking the memory if you set the pointer to NULL.
EDIT: The memory being leaked would be the memory being pointed to by the pointer in the array.
Setting items[5] to NULL doesn't delete the memory associated with the item, it simply sets the pointer to that item to NULL, therefore the memory is leaked.
You can delete the item by calling:
delete items[5];
Since C++ has not automatic garbage collection, you need to delete any memory you no longer need.