Why does C++ need delete[] ?

R

Roy Smith

I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?
 
V

Victor Bazarov

Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.

You could see the difference if you did a performance test on deleting
an array of size 1 versus a single object.

V
 
M

Method Man

Victor Bazarov said:
Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.

I can't imagine much of an optimization advantage by using "delete []". How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".
 
P

Peter Pan

"delete []" will call destructor of each object element in array, while
delete will only call the destructor of first one.


Method said:
Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.


I can't imagine much of an optimization advantage by using "delete []". How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".
 
E

E. Robert Tisdale

Roy said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

According to Bjarne Stroustrup,
"The C++ Programming Language: Third Edition",
Chapter 10 Classes, Section 4 Objects, Subsection 7 Arrays, page 250

"Like C, C++ doesn't distinguish between
a pointer to an individual object and
a pointer to the initial element of an array.
Consequently, the programmer must state whether
an array or an individual object is being deleted."
 
E

E. Robert Tisdale

Method said:
I can't imagine much of an optimization advantage by using "delete []".
How much does one table lookup really cost for the array size?

This would compel the implementation to store an array size
for individual objects as well as for arrays of objects.
And if "delete []" was that much more efficient,
why didn't they add a "free []" (along with "malloc[]") feature as well?

malloc doesn't call any constructor and
free doesn't call any destructor.
 
G

Gianni Mariani

Method said:
Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.


I can't imagine much of an optimization advantage by using "delete []". How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".

new X[N] is the equivalent of


// warning - this code is not tested or checked and guarenteed broken
template <typename X>
X * MyNew( unsigned N )
{
// need to guarentee alignment - so statement below might be broken
void * t = malloc( sizeof( int ) + sizeof( X ) * N );

if ( ! t )
{
throw bad_alloc();
}

X * ptr = sizeof( int ) + (char *) t;

for ( int i = 0; i < N; ++ i )
{
// perform construction
new ( ptr + i ) X();
// oops need to handle exception --- broken again
}

* ( int * ) t = N;

return ptr;
}

delete[] is equivalent to

template <typename X>
void MyDelete( X * ptr )
{
if ( ! ptr ) return;

void * t = ( void * )( (char *) ptr ) - sizeof( int ) );
int N = * ( int * ) t;

for ( int i = N; i --; )
{
// call destructor
( ptr + i )->~X();

// oops need to handle exception --- baroke
}

free( t );

return ptr;
}

The point is, comparing delete[] and free() makes little sense.
Also, if you made new and new[] do the same thing, you would pay the
penalty of an extra 4 bytes for every object you new()ed. This can be a
very expensive thing to do when you have very large numbers of small
objects to create.
 
V

Victor Bazarov

Method Man said:
Victor Bazarov said:
Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you
need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's
the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.

I can't imagine much of an optimization advantage by using "delete []".
How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".

Actually, historically, you _had_ to tell 'delete[]' how many to destroy
just like you have to tell 'new[]' how many to create.

I bet you can find more in "Design and Evolution of C++".

Victor
 
M

Method Man

E. Robert Tisdale said:
Method said:
I can't imagine much of an optimization advantage by using "delete []".
How much does one table lookup really cost for the array size?

This would compel the implementation to store an array size
for individual objects as well as for arrays of objects.

Which is exactly what "free" needs to know since it doesn't care if the
pointer passed to it is a single (POD) object or an array of objects. So why
is this such an issue with "delete"?
And if "delete []" was that much more efficient,
why didn't they add a "free []" (along with "malloc[]") feature as well?

malloc doesn't call any constructor and
free doesn't call any destructor.

I understand that. The reason I drew the parallel of "delete" to "free" was
to point out that, regardless of whether one is dealing with POD types or
user types, "free" doesn't require any knowledge of deallocating an array or
a single object. "delete" _could_ have been implemented the same way. But,
they opted to have "delete[]" specifically for arrays.
 
M

Method Man

Gianni Mariani said:
Method said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.


I can't imagine much of an optimization advantage by using "delete []". How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".

new X[N] is the equivalent of


// warning - this code is not tested or checked and guarenteed broken
template <typename X>
X * MyNew( unsigned N )
{
// need to guarentee alignment - so statement below might be broken
void * t = malloc( sizeof( int ) + sizeof( X ) * N );

if ( ! t )
{
throw bad_alloc();
}

X * ptr = sizeof( int ) + (char *) t;

for ( int i = 0; i < N; ++ i )
{
// perform construction
new ( ptr + i ) X();
// oops need to handle exception --- broken again
}

* ( int * ) t = N;

return ptr;
}

delete[] is equivalent to

template <typename X>
void MyDelete( X * ptr )
{
if ( ! ptr ) return;

void * t = ( void * )( (char *) ptr ) - sizeof( int ) );
int N = * ( int * ) t;

for ( int i = N; i --; )
{
// call destructor
( ptr + i )->~X();

// oops need to handle exception --- baroke
}

free( t );

return ptr;
}

The point is, comparing delete[] and free() makes little sense.

Understood after reading some of your code.
Also, if you made new and new[] do the same thing, you would pay the
penalty of an extra 4 bytes for every object you new()ed. This can be a
very expensive thing to do when you have very large numbers of small
objects to create.

Well, that's how it's always been done with malloc/free in terms of storing
the allocated size for every memory block in a table. I still don't see why
those extra 4 bytes became an issue all of a sudden in C++.
 
E

E. Robert Tisdale

Method said:
E. Robert Tisdale said:
Method said:
I can't imagine much of an optimization advantage by using "delete []".
How much does one table lookup really cost for the array size?

This would compel the implementation to store an array size
for individual objects as well as for arrays of objects.

Which is exactly what "free" needs to know since it doesn't care if the
pointer passed to it is a single (POD) object or an array of objects.
So why is this such an issue with "delete"?
And if "delete []" was that much more efficient,
why didn't they add a "free []" (along with "malloc[]") feature as well?

malloc doesn't call any constructor and
free doesn't call any destructor.

I understand that.
The reason I drew the parallel of "delete" to "free" was to point out that,
regardless of whether one is dealing with POD types or user types,
"free" doesn't require any knowledge
of deallocating an array or a single object.

`malloc' and `free' don't know anything about objects.
The standard doesn't require implementations to store
any information about how much storage was allocated.
`free' could be a dummy function that returns
without doing anything!
`delete' *must* invoke the destructor!
`delete []' must look for the size of the array stored by `new []'
and invoke the destructor for every element of the array.
"delete" _could_ have been implemented the same way.
But [Bjarne Stroustrup] opted to have "delete[]" specifically for arrays.

But language designers do *not* specify how compilers are implemented.
 
G

Gianni Mariani

Method Man wrote:
....
Well, that's how it's always been done with malloc/free in terms of storing
the allocated size for every memory block in a table. I still don't see why
those extra 4 bytes became an issue all of a sudden in C++.

A C++ allocator is able to have zero allocation overhead and in some
cases this is a significant advantage over free(). (only for classes for
which sizeof(Class) is larger than sizeof(void *)).

Maybe this distinction is insignificant. However, the point is that it
is the way it is. if you want to argue that the language should change,
comp.std.c++ is the newsgroup that will have interested (or
disinterested) ears and eyes. This ng is about the C++ standard as it is.
 
B

Branimir Maksimovic

Method Man said:
Victor Bazarov said:
Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Existence of 'delete' along with 'delete[]' allows some deallocation
code to be optimised a bit better. For example, if you are sure that
there is only one object to be destroyed, there is no need to look up
the size of the "array", so 'delete' is a bit more efficient than its
"array" counterpart.

I can't imagine much of an optimization advantage by using "delete []". How
much does one table lookup really cost for the array size? And if "delete
[]" was that much more efficient, why didn't they add a "free []" (along
with "malloc[]") feature as well?

I guess they chose to have "delete[]" to make it a compliment in syntax to
"new x[n]".

malloc/free does not call constructors/destructors.
expressions new[]/delete[] must lookup number of elements just
for one reason:
that is, how many times they need to call constructors/destructors.
Optimisation is that expressions new/delete does not call
constructors/destructors more than once so they don't lookup for
number of elements.
Other optimisation is in saving memory. new allocates less bytes
then new[] for objects that have destructors, cause there is no need to
store number of elements. And after all compiler can insert
identicall code for expressions new[]/new for types that don't have
destructors.
However all this heave not anything to do with operators new/delete/new
[]/delete[] that can have completely identical implementations.

Greetings, Bane.
 
S

Stuart Gerchick

Roy Smith said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

The scalar new allocates memory witout a hidden counter. if you use
the delete [] with the scalar new, the delete [] will either crash or
use whatever number it happens to find. If this number is greater
than 1 you are going to try and "free" memory in "front" of the actual
memory block. Not cool.

If you used new [] and the scalar delete, then the scalar delete will
not use the hidden counter. So, if there is more than 1 object, the
rest of them will not be deleted...and if there were zero objects
then you are going to try and delete 1. Not cool again.

There is no way in C++ as it stands for it to know which one you used
new or new []
 
D

Default User

Method said:
I can't imagine much of an optimization advantage by using "delete
[]". How much does one table lookup really cost for the array size?
And if "delete []" was that much more efficient, why didn't they add
a "free []" (along with "malloc[]") feature as well?


There is no such thing as malloc[]. malloc() is a function, returning a
void pointer, either to allocated memory of the requested size, or a
null pointer. Your analogy makes no sense.




Brian
 
A

Andrey Tarasevich

Roy said:
I understand that "delete xp" deletes a scalar object and "delete [] xp"
deletes an array of objects, but what I don't understand is why you need
to tell the compiler which you're doing.

When you do "delete [] xp", the delete procedure (not sure if that's the
right terminology) obviously knows how many objects were allocated by
the corresponding "new" call. So, why can't it just know whether you
did "new x" or "new x[n]"?

Firstly, that would require 'new' to store some household information in
each allocated memory block (just like 'new[]' usually does). This could
be considered wasteful, especially with smaller objects.

Secondly, one might want to choose different memory allocation
techniques for allocating single objects and arrays, since as long as
the type is fixed, single object allocation always allocates blocks of
the same size (and it's known at compile time) and array allocation
still allocates blocks of potentially varying sizes (not known at
compile time). For this reason, it might be useful to keep two
independent (read - independently overloadable) allocation mechanisms:
new/delete and new[]/delete[].
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,184
Messages
2,570,973
Members
47,530
Latest member
jameswilliam1

Latest Threads

Top