C ++ Gotchas Terms Terms 60: Failure to distinguish between monomer memory allocation and array memory allocation

zhaozj2021-02-08  571

Gotcha # 60: Failure to Distinguish Scalar and Array Allocation

Gotcha Terms 60: Failure to distinguish between monomer memory allocation and array memory allocation

Is a single widget and a widget array equal? of course not. Then why so many C programmers are surprised when discovering the "arrays) and single amount (SCALARS) to use different operators to spatially allocate and release"?

We all know how to spatially allocate and release for single Widget. We use New Operator and Delete Operator:

Widget * w = new widget (arg);

//.

Delete W;

NEW Operator is different from most other operators in C , and its behavior cannot be changed via overload. New operator always calls a function named Operator New to obtain some storage space and may initialize the space. For the case of Widget in the above code, use the New Operator will first result in a call to the Operator New function, which receives a size_t type as a parameter, then evoke the Widget constructor to perform uninitial storage space returned by the Operator New function, Thereby generating a Widget object.

Delete Operator in the code arouses a destructuring function for Widget, then calls a function called Operator Delete to match "The stored space that has now disappeared with the Widget object."

Memory allocation and behavioral changes are implemented via overload, replace or hide the Operator New function and the Operator delete function, not by modifying the behavior of New Operator and Delete Operator.

We also know how to spatially allocate and release the widgets array. But we don't use New Operator and Delete Operator:

w = new widget [n];

//.

Delete [] W;

Different, here we used new [] Operator and delete [] Operator (pronunciation, "Array New" and "Array Delete"). As New and Delete, the behavior of Array New Operator and Array Delete Operator is not changeable. Array New first evokes a function called Operator New [] to get some storage space, then (if necessary) from the first element of the array until the last element, the array element is default for each assigned space. Initialization action. Array Delete first follows each element in the secondary pin destroyed group, and then calls a function called Operator Delete [] to return space.

Belt one: It should be noted that the Vector library is used by the Vector library instead of array, usually a better design decision. The performance of the Vector is almost the same as Array, and is more secure and flexible. Generally speaking, Vector can be seen as "dexterous" Array, with Array has similar semantics. Only, when the vector is destroyed, its element is destroyed from the beginning to the end; in Array, the element is destroyed in the reverse order.

Memory management functions must be properly paired. If you use New to get the storage space, you should use Delete to release. If you use Malloc to get the storage space, you should use free to release. Together new and free, or use Malloc and delete to use some of the types on a particular platform, in some time, "work", but there is no guarantee makes such code to work properly. INT * IP = New INT (12);

//.

Free (ip); // is wrong!

IP = static_cast (malloc (intend));

* ip = 12;

//.

Delete IP; // is wrong!

Array assignment and deletion follow the same pairing rules. There is a common error that is released using the Array New allocated an array and use Scalar delete (used for single amount delete) to release. This code is just like New and Free's mismatch, perhaps you can work lucky under a particular situation, but it is very incorrect, and it is likely to cause errors in the future.

Double * dp = new double [1];

//.

Delete dp; // is wrong!

It should be noted that the compiler does not give a warning for the error practice of deleting an array using Scalar Delete (DELETE for single amount) because it cannot distinguish "pointer to array" and "pointer to a single element". In general, Array New is inserted into some additional information in an adjacency location of memory allocated by array to indicate the size of the memory block (block) and the number of elements included in the assigned array. Array Delete is using information and thus deletes arrays.

(Obtained by array new) This information is also different from the format of the information obtained via Scalar New. If you evoke Scalar delete to release the storage space allocated by the Array New, the corresponding information about the space size and the number of elements may be resolved by the Scalar delete error, resulting in undefined results - and it should be made by array delete F. The allocation of the SCALAR form and the allocation of Array may also use different memory pools. If so, use Scalar delete to returns a SCALAR POOL that is distributed to the Array Pool storage, which will result in catastrophic results.

DELETE [] dp; // is right!

This kind of flash in the two concepts allocated with SCALAR, and often occurs in the design of member functions for memory management:

Class widget {

PUBLIC:

Void * Operator new (SIZE_T);

Void Operator Delete (Void *, SIZE_T);

//.

}

The author of Widget Class is determined to customize Widgets memory management, but it does not take into account: Array Operator New Functions and Array Operator Delete functions The function of SCALARARARATOR form (Scalar Operator New and Scalar Operator delete have different names) Translation: The SCALAR form is Operator new () and operator delete (); and Array is Operator New [] () and Operator delete [] (), respectively, as described below). Widget * w = new widget (arg); // ok

//.

Delete W; // ok

W = new widget [n]; // OOPS!

//.

Delete [] W; // OOPS!

Since Widget Class does not declares the Operator New [] and Operator Delete [] functions, the Memory Management of the Widgets array will use the Global version of these functions. This may cause incorrect behavior, and the author of Widget Class should provide Operator New [] and Operator Delete [] member function versions.

If the truth is exactly the same, the above is just the correct behavior of intended, then the author of this category should clearly explain this in the future maintainer; otherwise, the maintainer is likely to provide those "lost" functions. Trying to "Correct" this "problem". The best way to make this design decision document is not adding, but directly through code:

Class widget {

PUBLIC:

Void * Operator new (SIZE_T);

Void Operator Delete (Void *, SIZE_T);

Void * Operator new [] (size_t n)

{RETURN :: Operator new [] (n);

Void Operator delete [] (void * p, size_t)

{:: Operator delete [] (p);

//.

}

Array New and Array Delete version of the INLINE Member Function version will not cause any additional consumption during operation; The global version of the function, not in repeated suspicion.

转载请注明原文地址:https://www.9cbs.com/read-397.html

New Post(0)