<C ++ primer> exercise 14.11 mentions:
Account * parray = new account [100];
Delete parray;
Delete [] parray;
The existence of square brackets will enable the compiler to obtain the array size and then the Destructor will be applied to each element in sequence for a total of size times. Otherwise, only one element is destructed.
In either case, all allocated space is returned to the free storage zone.
My question is: in either case, all allocated space is returned to the free storage zone?
For Delete parray, why is 100 elements deleted instead of a single account.
How does the compiler know whether the pointer parray actually points to an array or a single element? How does the compiler know the size of the array even if it points to an array in the free storage area.
Is it a compiler-assisted behavior?
Summary: Space release (there must be a log record allocated size) and calling destructor (type identification, different compilers implement different) adopt different mechanisms.
(1) generally, the distributor will automatically write a log (another structure before the memory is allocated and used) to record the size of the distribution and the sizeof of the allocated content.
Intuitively, both delete and delete [] input a void * If the log is not saved, you cannot know whether one or more units are allocated during the allocation.
Therefore, although the delete and delete [] operations are different, the Allocator reads this log during the release process to learn how much memory should be released. But from the programmer's perspective, since an array is allocated, delete [] should be used.
(2) The execution of the compilation with Delete [] in VC, and it is found that this "log" is a 4-byte long integer to record the number of array elements, next to the first element of the array.
But there is a premise: the object type (or its base class) has an explicit destructor. In other words, the Destructor is not trivial.
Otherwise, the log is not in front of the array. in fact, if the Destructor are trivial, you do not need to call the Destructor when you delete []. Therefore, VC treats Delete [] as Delete.
(3) because releasing the array space and calling the Destructor for the array are two independent parts, different mechanisms can be used for implementation.
The space release mechanism must be absolutely guaranteed. Therefore, even if you do not write Delete [], it will release all the spaces. The mechanism can be the front-end length information or not (such as the rear-end feature delimiter ).
The method of calling the Destructor can generally use the Front Length information (of course, there can be other methods ). When no [] prompt is displayed, the compiler treats the Destructor as an element without calling every destructor using arrays.
Ls: "But there is a premise: the object type (or its base class) has an explicit destructor. in other words, the Destructor are non-trivial. otherwise, the log is not in front of the array."
-- This indicates that the LS compiler does not use the Front Length information when releasing the array space. It can be seen that different mechanisms can be used to release the array space and call the Destructor for the array.
(4) Delete parray: the compiler obtains that the type information is a single pointer of the account. when the account is released, only one destructor is called.
Delete [] parray. If the type information obtained by the compiler is account [], it is processed according to the account array and the destructor of each element is called in sequence.
Note that the above is determined during the compilation process. The Compiler determines that different types of information are different in calling the destructor.
However, for memory release, the delete operation does not determine the size of the allocated memory through the type information. Where can I obtain the memory size information?
When we use operator new to allocate memory for a user-defined object, the memory we actually get is larger than the memory of the actual object. In addition to storing object data, you also need to record the memory size. This method is called Cookie. The implementation at this point is based on different compilers. (For example, MFC chooses to store the actual object data in the header of the allocated memory, while the latter part stores the boundary mark and memory size information. G ++ stores the relevant information in the first four parts of the allocated memory, and the actual data of the object is stored in the memory later .) When we use Delete operator to release memory, delete
Operator can correctly release the memory block pointed to by the pointer based on the information.
For the parray pointer, you can obtain the size pointing to the memory space based on such cookie information. Delete parray and delete [] parray are the same, and the cookie information is the same for the same pointer, therefore, the corresponding memory will be released. However, since the compiler understands that the types in the two cases are different, calling the Destructor may be different.
(5) Is it a compiler-assisted behavior?
That's right. Different compilers may use different methods. However, no matter what method is used, the compiler must remember the block size.
(6) Conversion from <valid tive C ++>
Clause 5: The New and delete operations must be in the same format.
What are the following statements?
String * stringarray = new string [100];
Delete stringarray;
Everything seems to be in an orderly manner-a new corresponds to a delete-but there is a large hidden error: the running status of the program will be unpredictable. At least 99 of the 100 string objects pointed to by stringarray will not be correctly destroyed, because their destructor will never be called.
Two things will happen when new is used. First, the memory is allocated (by using the operator new function, see terms 7-10 and M8), and then one or more constructors are called for the allocated memory. When using Delete, there are also two things: first, call one or more destructor for the memory to be released, and then release the memory (through the operator delete function, for details, see clause 8 and M8 ). For Delete, there is an important question: how many objects in the memory will be deleted? The answer determines how many destructor will be called.
Simply put, the pointer to be deleted points to a single object or an object array? Only you can tell Delete. If you use delete without parentheses, delete will point to a single object. Otherwise, it will point to an array:
String * stringptr1 = new string;
String * stringptr2 = new string [100];
...
Delete stringptr1; // delete an object
Delete [] stringptr2; // delete an array of Objects
What if you add "[]" before stringptr1? The answer is: it will be unpredictable;
What if you didn't add "[]" before stringptr2? The answer is: unpredictable.
For a fixed type such as int, the result is unpredictable, even if such a type does not have a destructor. Therefore, the rule for solving such problems is simple: if [] is used when you call New, [] is also used when you call Delete. If [] is not used when new is called, [] is not used when Delete is called.