Reputation: 2035
A* p = new A[5];
delete &p[2];
// error,why? Does it need to use delete []p
to delete together?
p is a pointer(p == &p[0]
),however, p[0],p[1]... is a type of object. why p[n] is not pointer?
Upvotes: 1
Views: 1340
Reputation: 49289
delete
works on pointers (and only pointers to dynamically allocated memory blocks) but you don't have an array of pointers, so delete
doesn't work on the array elements, it can only work on the array pointer. And it should be the delete []
operator in particular.
If you want to remove an element from the array, you must iterate the array, and when you reach the element you want to remove, start overwriting the array with the next element. Also, you might want to allocate a new, shorter array, and do that operation there, then delete the old array and set the array pointer to the new array.
Ideally, you should use an std::vector
class, which does everything for you automatically:
std::vector<A> v(5); // gives you a vector of 5 A elements
v.erase(v.begin() + 2); // erases the element at index 2
This way is less prone to errors and is preferred, and is just as fast and efficient as the error-prone manual way.
Now if you had an array/vector of pointers to elements, that would be a different matter, then you'd have to make sure you delete
the element and erase it from the vector. Naturally, if you use smart pointers, you can simply erase the pointer from the vector and it will be automatically deleted.
why p[n] is not pointer?
The [n]
operator for pointers is just a shortcut to deference a pointer with an offset. So p[2]
is equivalent to *(p + 2)
. And when you dereference a pointer, you get a reference to whatever it points to, in your case an A
instance. So delete p[2]
can only work if it is an array of A pointers, not A instances. Note that in your case &p[2]
will actually be a pointer, it will be the same value as p + 2
because the &
operator will take the address of the reference, but you should not use delete on it, as it itself doesn't point to dynamcally allocated memory, even if it itself happens to be in such memory.
As you yourself noted in the question p == &p[0]
but nonetheless, p != p[0]
. This means neither should you delete &p[0]
even if both are pointers to the same address. Since the memory for the array has been allocated with new []
it should be deallocated with delete []
, and you should not use the delete
operator on the array or any of its elements.
&p[0]
gives you the address of the first element in the array, which coincides with the beginning of the array, but p == &p[0]
is just a value comparison. p
may be "equal" to &p[0]
but it is not the same semantically, as p
is a pointer to A []
and &p[0]
is a pointer to A
.
Upvotes: 0
Reputation: 11116
Yes and no:
Yes, a call to new[]
must be paired with a single call to delete[]
.
No, that does not "delete together", as the result is just one entity (an array), not a collection of A
s. Therefore, you do not actually delete anything together.
No, you need not end the lifetime of all elements of the array at the same time. However, explicitly calling an destructor is something you might wish to leave to standard library components at this point.
Which brings us to:
What you seem to want to achieve:
End the lifetime of a single object of that array. Since it does not make any sense for the result to be an array with some kind of magic hole, you might want to consider std::vector<A>::erase
to deal with it. This will remove one element and move up all other elements so that the result behaves like an array where one element has been removed without leaving a hole.
Upvotes: 1
Reputation: 780994
What you delete has to exactly match what you allocated, you can't do partial deletions. The memory manager generally records information about the allocation based on the address that it returned. If you pass a different address to delete
, it won't be able to find the allocation information.
Upvotes: 3
Reputation: 36346
What would that achieve? You're trying to free the space of a single A, somewhere in the middle of a longer contiguous array of A's.
This simply doesn't work because it's against what delete
does.
when you do new[]
, your runtime gets you a sufficiently large set of memory to store the array of objects. If that memory isn't "lying around" anyways, the runtime asks the operating system to map memory pages into your processes' memory space.
Now, if you no longer use these pages, you can "give them back"; but, you must do that to the whole chunk of memory you got. That's because freeing less than a page can't work (because the OS can't assign it anywhere else), and because allowing for this kind of fragmentation would make page tables huge.
this is reflected in the documentation of free
: You can only free memory by handing free
the exact same address malloc
gave you.
Upvotes: 2