More Effective C ++ Terms 8

zhaozj2021-02-08  284

Terms 8: Understand a variety of different meanings New and Delete

Sometimes it seems that it is difficult to understand the terms of the C language. For example, the NEW ORATOR and the Difference of Operator NEW.

When you write this code:

String * ps = new string ("Memory Management");

The New is the new operator. This operator is like SizeOf is the language built-in, you can't change its meaning, and its function is always the same. It is necessary to complete into two parts. The first part is an object that assigns enough memory to accommodate the desired type. The second part is that it calls the constructor to initialize the object in the memory. New operators always do these two things, you can't change its behavior in any way.

What you can change is how to allocate memory for an object. The New operator calls a function to complete the required memory allocation, you can rewrite or overloading this function to change its behavior. The NEW operator is the name of the allocated memory call function is Operator New.

Function Operator New usually declares this:

void * operator new; Size_t size

The return value type is VOID * because this function returns an unprocessed (RAW) pointer, not initialized memory. (If you like, you can write an operator new function that can initialize memory before returning a pointer to store some values, but generally don't do this.) Parameter size_t determines how much memory allocation. You can add additional parameter overload functions Operator New, but the first parameter type must be SIZE_T. (For more information about Operator New, see Effective C Terms 8 to Terms 10.)

You usually don't call the Operator New directly, but once you do, you can call it like calling other functions:

Void * rawMemory = Operator New (SIZEOF (STRING));

Operator Operator NEW will return a pointer to point to a String type object.

Like Malloc, the Operator New's responsibilities are only allocated. It doesn't know anything about the constructor. The Operator New is a memory allocation. Pass the unprocessed pointer returned by the Operator New to an object is the work of the New operator. When your compiler meets this statement:

String * ps = new string ("Memory Management");

It generated or less similar to the following code (more details see Effective C Terms 8 and Terms 10, and my article in counting object.):

Void * memory = // Get unreated memory

Operator new (SIZEOF (STRING)); / / for String object

Call string :: string ("Memory Management") // Initialization

ON * Memory; // Memory

// Object

String * ps = // is the PS pointer pointing

Static_cast (memory); // New object

Note that the second step contains the call of the constructor, you are prohibited by a programmer from doing this. Your compiler doesn't have this constraint, it can do everything it wants to do. So if you want to create a heap object, you must use the New operator to initialize the object directly to the constructor. Placement New

Sometimes you really want to call the constructor directly. Calling constructor on an existing object is meaningless, because the constructor is used to initialize the object, and an object can only be initialized once when it is given to the initial value. But sometimes you have some (RAW) memory that have been assigned but have not been processed, you need to construct an object in these memory. You can use a special Operator New, which is called Placement New.

The following example is how Placement New uses, consider:

Class widget {

PUBLIC:

Widget (int widgetsize);

...

}

Widget * ConstructWidgetinbuffer (Void * Buffer,

Int widgetsize)

{

Return New (Buffer) Widget (Widgetsize);

}

This function returns a pointer, pointing to a Widget object, the object is assigned to the buffer of the function. This function may be useful when the program uses shared memory or Memory-Mapped I / O, because the object must be placed in a determination address or a memory allocated by the routine in this program. (See Terms 4, a different example of how to use Placement New.)

In ConstructWidGetinbuffer, the return of the returned expression is:

New (buffer) Widget (Widgetsize)

It looks a little strange this, but it is a use of the New operator. It is necessary to use an additional variable (Buffer), passed the variable to it when the New operator is hidden to call the Operator New function. The called Operator New function must accept the VOID * pointer parameters in addition to the mandatory parameter SIZE_T, pointing to the memory space occupied by the constructor. This Operator New is Placement New, it looks like this:

Void * Operator new (size_t, void * location)

{

Return Location;

}

This may be simpler than you expect, but this is what Placement New needs to do. After all, the purpose of Operator New is to assign memory to the object and return to the pointer to the memory. In the case of using Placement New, the caller has got a pointer to memory because the caller knows where the object should be placed. The Placement New must do the pointer to the transfer to it. (Nothing (but forced) parameter size_t has no name to prevent the compiler from warning to say that it is not used; see Terms 6.) Placement New is part of a standard C library (see Effective C Terms 49). In order to use Placement New, you must use statements #include (or if your compiler does not support this new style header name (see Effective C Terms 49), ).

Let's come back from Placement New, see the New Operator and Operator New relationship, you want to create an object on the pile, you should use the New operator. It assigns both memory and object call constructor. If you just want to allocate memory, you should call the Operator new function; it does not call the constructor. If you want to customize your own memory allocation procedure when you are built in the heap object, you should write your own Operator New function, then use the New operator, the New operator calls your custom Operator New. If you want to build an object in memory that has already got the pointer, you should use Placement New. (See Effective C Terms 7 and My Articles in C Terms 7 and My Articles.

Deletion and memory deallocation

In order to avoid memory leaks, each dynamic memory allocation must correspond to a dense DEALLOCATION. The relationship between the function Operator Delete and the Delete operator is the same as the relationship between Operator New. When you see these code:

String * ps;

...

Delete PS; // Using the Delete Operator

Your compiler generates code to destructure objects and release the memory occupied by the object.

Operator delete is used to release memory, which is declared this:

Void Operator Delete (Void * MemoryTobeDeallocated);

therefore,

Delete PS;

Leading the compiler to generate a similar like this:

PS-> ~ String (); // Call The Object's Dtor

Operator delete (ps); // deallocate the memory

// the Object Occupied

This has an implicit meaning if you just want to handle the memory that is not initialized, you should bypass the New and DELETE operators, and call the Operator New to get memory and Operator delete release memory to the system:

void * buffer = // Assign enough

Operator new (50 * sizeof (char)); // memory to accommodate 50 char

// There is no call constructor

...

Operator delete (buffer); // Release memory

// There is no call destructor

This is called Malloc and Free equivalent to C.

If you build an object in memory with Placement New, you should avoid using the delete operator in the memory. Because the DELETE operator calls Operator Delete to release the memory, but the memory containing the object is originally assigned by the Operator New, the Placement New just returns the pointer to it. Who knows what this pointer comes? And you should explicitly call the dominant destructive function of the object to unlock the impact of constructor:

/ / Assign and release the memory in shared memory

Void * mallocshared (size_t size);

Void Freeshared (Void * Memory);

Void * sharedmemory = mallocshared (sizeof (widget));

Widget * pw = // As shown above,

ConstructWidGetinbuffer (SharedMemory, 10); // Using // Placement New

...

Delete pw; // The result is uncertain! Shared memory from

// mallocshared, not Operator New

PW-> ~ widget (); // is correct. Destructure PW Points Widget,

/ / But no release

// Contains Widget's memory

Freeshared (PW); // is correct. Release PW pointing to shared memory

/ / But there is no calling function

As shown in the above example, if the RAW memory passed to the Placement New is dynamically allocated (by some unopened methods), if you want to avoid memory leak, you must release it. (See my article in counting objects About Placement Delete's comment.)

Arrays

Everything is going on so far, but I have to go. So far we have tested to create an object. How to allocate arrays? what happens?

String * ps = new string [10]; // allocate an array of

// Objects

The NEW used is still a New operator, but the behavior of the New operator is established to establish a little different from a single object when establishing an array. The first is that memory is no longer assigned with Operator New, replacing the equivalent array allocation function, called Operator New [] (often referred to as Array New). It can be overloaded as Operator New. This allows you to control the memory allocation of the array, just like you control a single object memory allocation (but there are some restrictions, see Effective C Terms 8).

(Operator new [] For C is a relatively new thing, so your compiler may not support it. If it does not support, no matter what the object type in the array, the global Operator New will be used to give each The array is allocated memory. It is difficult to rewrite the overall Operator new. This is not a task that can be easily accepted. By default, all Operator New handles Dynamic memory allocation, there will be an in-depth and universal impact of its behavior. And the global operator new has a normal signature (Normal SIGNATURE) (for a single parameter size_t, see Effective C Terms 9), so if You decided to declare it with your own method, you immediately make your program and other libraries (see Terms 27) Based on these considerations, the compiler in the lack of Operator New [] is not a reasonable design. .)

The second difference is the number of new operators called constructor. For arrays, the constructor of each object in the array must be called:

String * ps = // Calls Operator New [] 10

New string [10]; // String object allocates memory,

/ / Then call each array element

// String object default constructor.

Similarly when the Delete operator is used in an array, it calls a destructor for each array element and then calls Operator Delete to release the memory.

Just like you can replace or overload Operator Delete, you also replace or overload Operator Delete []. There are some restrictions on their overloaded methods. Please refer to the excellent C textbook. (For information on excellent C textbooks, see the recommendation 285 pages of this book) The New and Delete operators are built-in, and their behavior is not controlled by your control, and all the memory allocations and release functions they call can be controlled. When you want to customize New and Delete operators, please remember that you can't really do this. You can only change their methods taken to complete their features, and the features they have completed are fixed by the language and cannot be changed. (You can modify how the do what do, but what the the do is fixed by the language)

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

New Post(0)