junlin
junlin

Reputation: 2035

Why can't I delete pointer alone from an array of objects?

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

Answers (4)

dtech
dtech

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

danielschemmel
danielschemmel

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 As. 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

Barmar
Barmar

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

Marcus M&#252;ller
Marcus M&#252;ller

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

Related Questions