Dispose of object array: Delete and delete[]

Source: Internet
Author: User

<<c++ primer>> Exercise 14.11 mentions:
Account *parray=new account[100];
Delete Parray;
delete [] parray;
The presence of square brackets causes the compiler to get the array size (size) and then the destructor is then applied to each element sequentially, with a total size. Otherwise, only one element is refactored.
In either case, all allocated space is returned to the free storage area.

My question is: why, in either case, the allocated space is returned to the free storage area?
For delete Parray, why not delete a single account element, but delete 100.
How does the compiler know Parray this pointer actually points to an array or a single element, and even if you know the array that points to a free store, how does the size of the array know.
Compiler helper behavior.

Summary: Space release (there must be a log record allocation size) and call destructors (type recognition, different compiler implementations differ) adopt different mechanisms.

(1) Generally at the time of allocation the allocator will automatically write a log (usually in the allocation of memory before the use of another structure), to record the size of allocations, the allocation of the content of sizeof and so on.
Intuitively, delete and delete[] all pass in a void* if you do not save the log, you cannot know whether or not the allocation is assigned to one or more cells.
So although delete and delete[] are different, the allocator reads this log during the release process to see how much memory should be freed, but from the programmer's point of view, since the array is allocated, it should be used delete[]

(2) in the VC under the Assembly with the delete[] implementation, found that the "log" is a 4-byte long integer record array elements, immediately before the first element of the array.
However, there is a premise that an object type (or its base class) has an explicit destructor. In other words, destructors are non-trivial.
Otherwise, there is no such log in front of the array. In fact, for the destructor is trivial, delete[] do not need to call its destructor, so at this time the VC delete[] as delete the same processing.

(3) becausereleasing the array space and calling the destructor as an array is two separate parts, you can use a different mechanism to implement it.
The mechanism to free space is absolutely guaranteed. Therefore, even if you do not write delete[], it will also release all the space, its mechanism can be the length of the predecessor information, or not (such as the post-feature separator and so on).
and the call destructor can generally use the way of the front length information(There can be other ways, of course). In the absence of a [] prompt, the compiler will call a destructor as an element without using an array to invoke each destructor.
LS: "But there is a premise: the object type (or its base class) has an explicit destructor. In other words, destructors are non-trivial. Otherwise, there is no such log in front of the array. "
-This means that the compiler used by LS does not use the preceding length information when it frees the array space. Thus, releasing the array space and calling the destructor for an array can really use different mechanisms

(4) Delete Parray, the compiler gets the type information is a single pointer to the account, then when released, only one destructor is called.
Delete[] Parray, the type information that the compiler obtains is the account[] type, which is processed according to the account array, and the destructor of each element is called sequentially.

Note that the above is determined during compilation,The compiler recognizes different types of information, which determines that the destructor is called differently.

Butfor Memory deallocation, the delete operation does not determine the allocated memory size by type information, so where does the memory size information get from?
When we use operator new to allocate memory for a custom type object, we actually get more memory than the actual object, which, in addition to storing the object data, needs to record the size of the memory, which is called a cookie. The implementation of this point is different depending on the compiler. (for example, MFC chooses to store the actual data of the object in the head of the allocated memory, while the latter part stores the bounding flag and the memory size information.) The g++ uses the first 4 of the allocated memory to store information about itself, while the memory behind it stores the actual data of the object. When we use delete operator for a memory release operation, delete operator can correctly release the block of memory that the pointer points to based on that information.
For Parray pointers, you can get to the size of the memory space based on such cookie information, delete Parray and delete[] Parray are the same, the same pointer, the cookie information is the same, so the corresponding memory will be released. However, because the compiler understands that the types in both cases are different, the call destructor will be different.

(5) It is compiler helper behavior.
Yes, it is. The specific methods that may be used by different compilers may not be the same, but regardless of the method used, the compiler must remember that block size.

(6) Transfer from <<effective c++>>
Clause 5: The corresponding new and delete should be in the same form

There is nothing wrong with the following statement.
String *stringarray = new string[100];
Delete Stringarray;
Everything seems to be in order--a new one corresponds to a delete--but there is a big mistake: The running of the program will be unpredictable. At the very least, 99 of the 100 string objects that Stringarray points to will not be properly destroyed because their destructors are never called.
There are two things that happen when you use new. First, the memory is allocated (via the operator new function, see clause 7-10 and Clause M8), and then one or more constructors are called for the allocated memory. When using delete, two things happen: first, to call one or more destructors for the memory being freed, and then to free up memory (via the operator delete function, see clauses 8 and M8). For delete, there is an important question: how many objects in memory are to be deleted. The answer determines how many destructors will be called.
The simple question is whether the pointer to be dropped points to a single object or an array of objects. That's all you have to tell the delete. If you use delete without parentheses, delete will think of pointing to a single object, otherwise it will assume that it is pointing to an array:
String *stringptr1 = new string;
String *stringptr2 = new string[100];
...
Delete stringptr1;//deletes an object
Delete [] stringptr2;//delete an array of objects
What happens if you add "[]" before the stringptr1. The answer is: that will be unpredictable;
What if you didn't add "[]" before the STRINGPTR2? The answer, too, is unpredictable.
For a fixed type such as int, the result is also unpredictable, even if such a type does not have a destructor. So the rules for solving this kind of problem are simple: if you use [] when you call new, you also use [] when you call delete. If [] is not used when calling new, do not use [] when calling delete.

CPP code   #include  <iostream>      using namespace std;      struct foo   {       ~foo () {}; //is removed, the number is not recorded.   };         int main (int argc,char *argv[])    {            foo* f = new foo;         delete f;        f=0;         delete f;           foo* fa =  new foo[8];        printf ("%u/n",  * (char *) fa -  4));  //output 8: Auxiliary destructor .        /*        For an array of objects with an explicit destructor,        compiler allocates 4 bytes in front of the array to store the number of array elements          (Alsois the number of times the destructor needs to be called),        because you must know the actual number of elements in the array,       delete[ ] to know how many destructors need to be called.        */        delete fa; // Some compilers will have exceptions here .        //use delete instead of delete[] to release space allocated with new[] This behavior is undefined,         //is the implementation of the compiler to determine the         fa = 0;         delete fa;            return 0;  }  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.