What Is the Array Form of 'Delete'

What is the array form of 'delete'?

The array form of delete is:

delete [] data;

Edit: But as others have pointed out, you shouldn't be calling delete for data defined like this:

int data[5];

You should only call it when you allocate the memory using new like this:

int *data = new int[5];

Deleting array elements in JavaScript - delete vs splice

delete will delete the object property, but will not reindex the array or update its length. This makes it appears as if it is undefined:

> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> delete myArray[0]
true
> myArray[0]
undefined

Note that it is not in fact set to the value undefined, rather the property is removed from the array, making it appear undefined. The Chrome dev tools make this distinction clear by printing empty when logging the array.

> myArray[0]
undefined
> myArray
[empty, "b", "c", "d"]

myArray.splice(start, deleteCount) actually removes the element, reindexes the array, and changes its length.

> myArray = ['a', 'b', 'c', 'd']
["a", "b", "c", "d"]
> myArray.splice(0, 2)
["a", "b"]
> myArray
["c", "d"]

Why does the delete[] syntax exist in C++?

Objects in C++ often have destructors that need to run at the end of their lifetime. delete[] makes sure the destructors of each element of the array are called. But doing this has unspecified overhead, while delete does not. This is why there are two forms of delete expressions. One for arrays, which pays the overhead and one for single objects which does not.

In order to only have one version, an implementation would need a mechanism for tracking extra information about every pointer. But one of the founding principles of C++ is that the user shouldn't be forced to pay a cost that they don't absolutely have to.

Always delete what you new and always delete[] what you new[]. But in modern C++, new and new[] are generally not used anymore. Use std::make_unique, std::make_shared, std::vector or other more expressive and safer alternatives.

Why is there a special new and delete for arrays?

Objects created with new[] must use delete[]. Using delete is undefined on arrays.

With malloc and free you have a more simple situation. There is only 1 function that frees the data you allocate, there is no concept of a destructor being called either. The confusion just comes in because delete[] and delete look similar. Actually they are 2 completely different functions.

Using delete won't call the correct function to delete the memory. It should call delete[](void*) but instead it calls delete(void*). For this reason you can't rely on using delete for memory allocated with new[]

See this C++ FAQ

[16.13] Can I drop the [] when
deleteing array of some built-in type
(char, int, etc)?

No!

Sometimes programmers think that the
[] in the delete[] p only exists so
the compiler will call the appropriate
destructors for all elements in the
array. Because of this reasoning, they
assume that an array of some built-in
type such as char or int can be
deleted without the []. E.g., they
assume the following is valid code:

void userCode(int n)  {
char* p = new char[n];
...
delete p; // ← ERROR! Should be delete[] p !
}

But the above code is wrong, and it
can cause a disaster at runtime. In
particular, the code that's called for
delete p is operator delete(void*),
but the code that's called for
delete[] p is operator
delete[](void*)
. The default behavior
for the latter is to call the former,
but users are allowed to replace the
latter with a different behavior (in
which case they would normally also
replace the corresponding new code in
operator new[](size_t)). If they
replaced the delete[] code so it
wasn't compatible with the delete
code, and you called the wrong one
(i.e., if you said delete p rather
than delete[] p), you could end up
with a disaster at runtime.

Why does delete[] exist in the first place?

Whether you do x or y:

 char * x = new char[100]; 
char * y = new char;

Both are stored in char * typed variables.

I think the reason for the decision of delete, and delete[] goes along with a long list of decisions that are in favor of efficiency in C++. It is so that there is no enforced price to do a lookup of how much needs to be deleted for a normal delete operation.

Having 2 new and new[] seems only logical to have delete and delete[] anyway for symmetry.

How does delete[] know it's an array?

The compiler doesn't know it's an array, it's trusting the programmer. Deleting a pointer to a single int with delete [] would result in undefined behavior. Your second main() example is unsafe, even if it doesn't immediately crash.

The compiler does have to keep track of how many objects need to be deleted somehow. It may do this by over-allocating enough to store the array size. For more details, see the C++ Super FAQ.

Why [] is used in delete ( delete [] ) to free dynamically allocated array ?

Scott Meyers says in his Effective C++ book: Item 5: Use the same form in corresponding uses of new and delete.

The big question for delete is this: how many objects reside in the memory being deleted? The answer to that determines how many destructors must be called.

Does the pointer being deleted point to a single object or to an array of objects? The only way for delete to know is for you to tell it. If you don't use brackets in your use of delete, delete assumes a single object is pointed to.

Also, the memory allocator might allocate more space that required to store your objects and in this case dividing the size of the memory block returned by the size of each object won't work.

Depending on the platform, the _msize (windows), malloc_usable_size (linux) or malloc_size (osx) functions will tell you the real length of the block that was allocated. This information can be exploited when designing growing containers.

Another reason why it won't work is that Foo* foo = new Foo[10] calls operator new[] to allocate the memory. Then delete [] foo; calls operator delete[] to deallocate the memory. As those operators can be overloaded, you have to adhere to the convention otherwise delete foo; calls operator delete which may have an incompatible implementation with operator delete []. It's a matter of semantics, not just keeping track of the number of allocated object to later issue the right number of destructor calls.

See also:

[16.14] After p = new Fred[n], how does the compiler know there are n objects to be destructed during delete[] p?

Short answer: Magic.

Long answer: The run-time system stores the number of objects, n, somewhere where it can be retrieved if you only know the pointer, p. There are two popular techniques that do this. Both these techniques are in use by commercial-grade compilers, both have tradeoffs, and neither is perfect. These techniques are:

  • Over-allocate the array and put n just to the left of the first Fred object.
  • Use an associative array with p as the key and n as the value.

EDIT: after having read @AndreyT comments, I dug into my copy of Stroustrup's "The Design and Evolution of C++" and excerpted the following:

How do we ensure that an array is correctly deleted? In particular, how do we ensure that the destructor is called for all elements of an array?

...

Plain delete isn't required to handle both individual objects an arrays. This avoids complicating the common case of allocating and deallocating individual objects. It also avoids encumbering individual objects with information necessary for array deallocation.

An intermediate version of delete[] required the programmer to specify the number of elements of the array.

...

That proved too error prone, so the burden of keeping track of the number of elements was placed on the implementation instead.

As @Marcus mentioned, the rational may have been "you don't pay for what you don't use".


EDIT2:

In "The C++ Programming Language, 3rd edition", §10.4.7, Bjarne Stroustrup writes:

Exactly how arrays and individual objects are allocated is implementation-dependent. Therefore, different implementations will react differently to incorrect uses of the delete and delete[] operators. In simple and uninteresting cases like the previous one, a compiler can detect the problem, but generally something nasty will happen at run time.

The special destruction operator for arrays, delete[], isn’t logically necessary. However, suppose the implementation of the free store had been required to hold sufficient information for every object to tell if it was an individual or an array. The user could have been relieved of a burden, but that obligation would have imposed significant time and space overheads on some C++ implementations.

deleting c++ array from heap and memory leak

Calling delete on an array without using [] results in Undefined Behaviour. The Undefined Behaviour might be that the array is correctly deleted, which appears to be what you observed. You can't rely on this, however.

C++ array delete operator syntax

You can check this MSDN link: delete[N] operator. The value is ignored.

EDIT
I tried this sample code on VC9:

int test()
{
std::cout<<"Test!!\n";
return 10;
}

int main()
{
int* p = new int[10];
delete[test()] p;
return 0;
};

Output is: Test!!

So the expression is evaluated but the return value is ignored.
I am surprised to say the least, I can't think of a scenario why this is required.

C++ Array of pointers: delete or delete []?

delete[] monsters;

Is incorrect because monsters isn't a pointer to a dynamically allocated array, it is an array of pointers. As a class member it will be destroyed automatically when the class instance is destroyed.

Your other implementation is the correct one as the pointers in the array do point to dynamically allocated Monster objects.

Note that with your current memory allocation strategy you probably want to declare your own copy constructor and copy-assignment operator so that unintentional copying doesn't cause double deletes. (If you you want to prevent copying you could declare them as private and not actually implement them.)



Related Topics



Leave a reply



Submit