9

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?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    The obviuos reason for delete[] to be is it will call destructors for array elements. See http://stackoverflow.com/questions/659270/why-is-there-a-special-new-and-delete-for-arrays – Captain Comic Sep 12 '10 at 09:35
  • Perhaps a more interesting question would be why `delete[]` (and `new[]`) exist when you have `std::vector`. – jamesdlin Sep 12 '10 at 10:12
  • 2
    @jamesdlin: Because we didn't always have `std::vector`? And because `std::vector` wouldn't work without them? – Oliver Charlesworth Sep 12 '10 at 10:16
  • 1
    And because the C++ language allows users to implement the behaviour of `std::vector` themselves, or more likely other things which are similar to `std::vector` but different in some useful way. The language is designed to support low-level and specialised development. – Steve Jessop Sep 12 '10 at 11:12
  • I am surprised how many told me the difference rather then why the 2nd exist. –  Sep 12 '10 at 12:23
  • @acidzombie24: not that surprising to me, since the difference is one of those things drummed into you pretty hard if you learn C++ formally. Answers like Charles's or Hans's, that address the motivation, are trying to get inside the design process of C++, which isn't taught nearly as much (and isn't vital to actually use the language, although I'd argue it's pretty darn useful). – Steve Jessop Sep 12 '10 at 17:33
  • 1
    @Oli Charlesworth: But you could implement `std::vector` with `realloc` and placement `new` instead of `new[]` (and that would support reallocating memory in-place). – jamesdlin Sep 12 '10 at 17:56
  • 1
    Actually, I realize `realloc` wouldn't work if the memory needs to be moved since there'd be no opportunity to do proper copy construction and destruction. Still, there's `malloc` and `free`, and `std::vector` doesn't use `new[]` directly anyway; it uses the specified allocator. – jamesdlin Sep 12 '10 at 18:51
  • @jamesdlin: Sure, `vector` doesn't use `new[]` and `delete[]` at all. They construct/destruct the elements at allocation/deletion, whereas `vector` must construct/destruct elements in response to `insert`, `push_back`, `resize`, etc. No earlier, and no later. Boost.Array might be a better example. You *could* implement Boost.Array on top of `vector`, if `vector` was the only means provided by C++ to allocate an array. But it's a bit unsatisfactory. It makes sense to me that if C++ defines arrays, it should define a way of allocating one... – Steve Jessop Sep 13 '10 at 18:17
  • ... Since dynamically-allocated arrays are rarely needed, `new[]` should be used rarely, which is fine. On the rare occasions where someone is programming at a low enough level to need a dynamically-allocated array, C++ gives you one. The downside of that, of course, is the need to slap every single new C++ programmer with a rolled-up newspaper until they learn to use `vector` (or `deque`) where possible, but that's pretty much also true of every single other difference between C++ and C ;-) – Steve Jessop Sep 13 '10 at 18:21
  • Just making a note. I'm not asking why new[] exist, just why delete[] exist. new[] has params, delete does not. But the answer explained why well enough. –  Sep 18 '10 at 01:47

4 Answers4

19

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.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • What?? Could someone give an example on where the number of destructors can not be determined on compile time? – lvella Apr 21 '12 at 22:12
  • @Ivella: How about in this function: `void freearray(Type* x) { delete[] x; }` – CB Bailey Apr 21 '12 at 22:38
  • and new[] usually put the number of objects at the beginning of the memory - although you can always calculate the size in runtime, I guess it is a time/space trade-off – Baiyan Huang Sep 11 '12 at 01:39
  • @lvella to get the number of objects, we need: sizeof(allocation)/sizeof(Type), while the sizeof(allocation) is stored by heapmanager somewhere else, you have to get it in runtime, not compile time – Baiyan Huang Sep 11 '12 at 01:40
3

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.

alxx
  • 9,897
  • 4
  • 26
  • 41
  • 7
    If you `delete` something that was the result of `new xxx[N]`, you get _undefined behaviour_. Calling the destructor on only the first object is just one possible result. – CB Bailey Sep 12 '10 at 09:36
3

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

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • _@Hans_, this is perhaps a somewhat elliptical answer... but great as a demonstration why `delete[]` is needed. +1 – stakx - no longer contributing Sep 12 '10 at 09:42
  • 1
    @stakx: it doesn't demonstrate `delete[]` is *needed*, as such - the implementation could somehow flag whether an allocation is an array or not, just as it currently tracks the length of all allocations made with `new[]`. Then `delete` could check the flag and just do the right thing. Deleting the first element of an array is always wrong, so there's no need for a syntax to do it. – Steve Jessop Sep 12 '10 at 11:15
  • Erm, no, hard to implement vector::operator[] if there was no syntax for that. – Hans Passant Sep 12 '10 at 11:33
  • 1
    @Steve: that would require a runtime test, which C++ usually tries to avoid when possible. – Mike Seymour Sep 12 '10 at 12:13
  • @Mike Seymour: I thought about that too but chances are the length is hardcoded as a const so shouldnt passing in the const be best? I also thought a quick if statement to see if its an array or not would take very few cycles and space. Then i remember i havent implemented my own delete yet –  Sep 12 '10 at 12:26
  • @Mike: true, but pretty much any memory allocator is going to involve a branch of some kind, somewhere. Avoiding this one is nice (as long as you don't mind occasional extra work, for example to write classes like `shared_array`), but not it's not as though C++ would be unworkable without that. – Steve Jessop Sep 12 '10 at 12:33
  • 1
    @Hans: I don't know what you mean. What does `vector::operator[]` have to do with deleting anything? My complaint is that you've said, "write the code for deleting an array vs. [something that's invalid]". Who cares what the code looks like to do something that's invalid? In our imagined version of C++, `delete array` would *mean*, "delete the whole array", and there would be no way to say, "delete the first element". `vector` uses an explicit call to the destructor to destroy elements, so that's unaffected. – Steve Jessop Sep 12 '10 at 12:43
  • 1
    @Steve: sorry, I had no idea that you were contemplating an imaginary version of the C++ language. My answer was based on the real one, the one that inherited the broken C arrays. – Hans Passant Sep 12 '10 at 12:49
  • _@Steve_, I also can't think of a reason why C++ should allow something which doesn't make sense, but it obviously does. That's why I sort-of like Hans' answer: There's probably no way to get it right with `delete` no matter what you try; thus you need something other than `delete`. (*tadaa!*, `delete[]` to the rescue, although he didn't say so in his original answer -- thus my comment about the answer being "somewhat elliptical".) – stakx - no longer contributing Sep 12 '10 at 13:59
  • 1
    @Hans: when you said, "assume delete[] didn't exist", you embarked upon a consideration of an imaginary version of the C++ language, which I continued. If you're unwilling to consider hypotheticals, you probably shouldn't attempt a proof by contradiction ;-) Clearly if, as you hypotheise, `delete[]` didn't exist, then `delete` would be the way to delete arrays. It could quite easily be made to work, although as Mike says, the cost of my flag implementation would be a runtime check to distinguish arrays from "normal objects". Or objects could just be arrays of size 1, also costing a branch. – Steve Jessop Sep 12 '10 at 17:15
  • hahah. Hey guys Steve Jessop is completely right (everything on this page 100%). Also i marked Charles Bailey answer for a reason. My question was of the point that delete can delete the entire array if it is an array and not do the wrong thing (deleting or dtoring the first element only). Steves comment was actually what i was thinking every time. Anyways it looks like its an optimization thing and maybe a feature in case you want to overload array allocation/new only. –  Sep 12 '10 at 17:21
  • @stakx: the reason C++ allows something that doesn't make sense is what Hans says. A pointer to the first element of an array isn't distinguished in the type system from a pointer to some single heap-allocated object, or from a pointer to the middle of an array. If you call `delete` to "free the first element of an array", instead of `delete[]` to free the whole array, the C++ language as it stands can't catch the error, so it's "allowed" only in the sense that you can write it but it's UB. A slightly modified C++ language, with some runtime costs, could catch it. So can a debugging allocator. – Steve Jessop Sep 12 '10 at 17:25
  • _@Steve_, I understood your point quite well, and my sentence was meant to agree with your opinion. The present argument as I see it is this: Hans showed that the present-day, real-world C++ without one feature (namely `delete[]`) would be missing something crucial, therefore that feature cannot be omitted. You, on the other hand, rightly state that if C++ did things a little smarter, `delete[]` wouldn't be necessary. You're both right, only perhaps you're considering C++ from a more "idealistic" point of view, while Hans' is the "realistic". I agree with you both. – stakx - no longer contributing Sep 12 '10 at 19:04
  • @stakx: Actually i believe without delete[] one can write an implementation of delete without any loss excepting the ability to overload delete[] (because it doesnt exist anymore) –  Sep 12 '10 at 20:05
1

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.

Alexander Rafferty
  • 6,134
  • 4
  • 33
  • 55
  • 1
    To be fair, you could say the same for `delete [] b`; how does it know that there are 25 items in the array? The answer is behind-the-scenes meta-information. In principle, the compiler could also store a boolean array/non-array flag in this meta-information. I think Charles' answer is the real reason. – Oliver Charlesworth Sep 12 '10 at 10:11
  • 2
    Even plain `delete` needs meta-information to be able to release the memory back to the heap, for example pointers to previous and next allocated blocks or something similar (heavily implementation dependent). – fredoverflow Sep 12 '10 at 15:14
  • The reason for `delete` and `delete[]` is so the compiler knows if you want to delete just that block or the whole array. – Alexander Rafferty Sep 12 '10 at 21:39