In-depth analysis of C ++ new

Source: Internet
Author: User
The new and delete operators are used to dynamically allocate and revoke memory.

New usage:

1. Open
Set up a single variable address space

1) New
Int; // open up a bucket for storing arrays and return an address pointing to the bucket. int * A = new int
That is, assign an int type address to the integer pointer.

2) int
* A = new int (5) serves the same purpose as above, but at the same time, the integer is assigned to 5

2. Open
Split array space

I
Dimension: int * A = new int [100]; opens up an integer array space of 100

II
Dimension: int ** P;


P = new int * [10];


For (INT I = 0; I <10; I ++)


P [I] = new int [20];

3.
Dimension and above: so on.

General Usage: New Type [initial value]

Delete usage:

1. int * A = new
Int;

Delete
A; // release the space of a single int

2. int * a = new
Int [5];

Delete
[] A; // release the int array space

 

You cannot directly access the struct space opened by new.
It can be accessed only through the variable name.

New and delete can be used for dynamic development and withdrawal
Pin address space. when programming, if you use a variable (usually an array temporarily stored), you need to use it again next time, but want to save the effort of re-initialization, you can open up a space each time you start to use it.
Undo it after use.

 

"New" is a key word of C ++ and also an operator. There are many topics about new, because it does compare
Complicated and mysterious. Next I will summarize the new-related content.

New Process

When we use the keyword new to dynamically create an object on the stack, it actually does three things: getting a piece of memory space,
Call the constructor and return the correct pointer. Of course, if we create a simple type variable, the second step will be omitted. Suppose we have defined the following Class:

Class

{

Int I;

Public:

A (int _ I): I (_ I * _ I ){}

Void Say () {printf ("I = % dn ",
I );}

};

// Call new:

A * pa = new A (3 );

The above process of dynamically creating an object is roughly equivalent to the following three statements (only in general ):

A * pA = (A *) malloc (sizeof ());

Pa-> A: A (3 );

Return Pa;

Although from the effect perspective, these three sentences also obtain a valid pointer PA pointing to the object on the stack, the difference is that when
When malloc fails, it does not call the allocation memory failure handler new_handler, but uses new. Therefore, we should try to use new unless there are some special
.

Three new forms

So far, all new mentioned in this Article refer to "new operator" or "new ".
Expression_r_r ", but in fact new mentioned in C ++ may at least represent the following three meanings: new operator, Operator
New and placement new.

New
Operator is the new we usually use, and its behavior is the three steps mentioned above. We cannot change it. However, if the behavior in a specific step does not meet our specific requirements
We may change it. The last step in the three steps is simply to convert the pointer type. There is nothing to say, and this conversion is not required in the compiled code. It is just a human understanding.
No. But there is something in the first two steps.

The first step of new operator is to allocate memory by calling operator.
New, the new here is actually the same operator as addition, subtraction, multiplication, division, so it can also be overloaded. Operator
New by default, the code for allocating memory is called first to get a heap space. If it succeeds, the code is returned. If it fails, a new_hander is called instead, and then the previous code is repeated.
Process. If we are not satisfied with this process, we can reload operator new to set the desired behavior. For example:

Class

{

Public:

Void * operator new (size_t size)

{

Printf ("Operator
New calledn ");

Return
: Operator new (size );

}

};

A * A = new ();

Operator
New calls the original global new to output a sentence before memory allocation. Global Operator
New can also be reloaded, but in this way, you can no longer recursively use new to allocate memory, but you can only use malloc:

Void * operator new (size_t size)

{

Printf ("Global newn ");

Return malloc (size );

}

Correspondingly, delete also has Delete operator and operator.
Delete: the latter can also be reloaded. In addition, if operator new is reloaded, it should also be reloaded accordingly.
Delete, which is a good programming habit.

The third form of new -- Placement
New is used to implement positioning and construction, so we can implement new
The second step in the three-step operator operation is to construct an object on the memory after obtaining a piece of memory that can accommodate the specified type of objects, which is similar to the previous Code
"P-> A: A (3);", but this is not a standard syntax. The correct syntax is placement New:

# Include <New. h>

Void main ()

{

Char s [sizeof (a)];

A * P = (A *) S;

New (p) A (3); // P-> A: A (3 );

P-> say ();

}

The reference to the opposite file <New> or <new. h> is required.
Use placement new. Here, the strange way of writing "New (p) A (3)" is placement.
New, which implements the function of constructing an object with the specified type of constructor at the specified memory address. The subsequent A (3) is an explicit call to the constructor. It is not difficult to find that the specified address here is
It can be a stack or a heap. placement does not distinguish this. However, do not directly use placement new unless necessary
After all, this is not a formal way to construct objects, but a step of new operator. Use new
Operator local compiler will automatically generate a pair of placement
New Call code, so it will also generate the code that calls the Destructor when using Delete. If placement is used on the stack as above
New, you must manually call the destructor, which is the only situation for explicitly calling the Destructor:

P-> ~ A ();

When we think the default new
Operator's memory management cannot meet our needs, but we want to manually manage the memory, placement
New is useful. Allocator in STL uses this method, and uses placement new to implement more flexible and effective memory management.

Handle memory allocation exceptions

As mentioned above, operator
The default action of new is to request memory allocation. If it succeeds, this memory address is returned. If it fails, a new_handler is called and then the process is repeated. Therefore, you want
When operator new is returned during execution, it must meet one of the following conditions:

L points
Memory configured successfully

L new_handler
Bad_alloc exception thrown in

L new_handler
To end the program.

Therefore, we can assume that operator new acts like this by default:

Void * operator new (size_t size)

{

Void * p = null

While (! (P = malloc (size )))

{

If (null =
New_handler)

Throw
Bad_alloc ();

Try

{

New_handler ();

}

Catch (bad_alloc
E)

{

Throw
E;

}

Catch (...)

{}

}

Return p;

}

By default, new_handler throws a bad_alloc exception.
The loop is executed only once. If you do not want to use the default behavior, you can define a new_handler and use the std: set_new_handler function to make it take effect.
In the custom new_handler, we can throw an exception, end the program, or run some code to make it possible that memory is idle, so that the next allocation may succeed.
You can use set_new_handler to install another possibly more effective new_handler. For example:

Void MyNewHandler ()

{

Printf ("New handler called! N ");

Throw std: bad_alloc ();

}

Std: set_new_handler (MyNewHandler );

Here, the new_handler program will output a sentence before throwing an exception. Note that
The new_handler code should avoid nested calls to new, because if the call to new fails, it may cause calls to new_handler,
This leads to infinite recursive calls. -- This is what I guess, and I have never tried it.

During programming, we should note that an exception may be thrown to the new call, so we should
Note that it is transactional, that is, it is not possible to throw an exception because of the call to new, which leads to the emergence of incorrect program logic or data structures. For example:

Class someclass

{

Static int count;

Someclass (){}

Public:

Static someclass *
Getnewinstance ()

{

Count ++;

Return new
Someclass ();

}

};

The static variable count is used to record the number of instances generated for this type. In the above Code
If an exception is thrown, the number of instances does not increase, but the value of the count variable has already exceeded, so that the data structure is damaged. The correct statement is as follows:

Static someclass * getnewinstance ()

{

Someclass * P = new someclass ();

Count ++;

Return P;

}

In this way, if new fails, an exception is thrown directly, and the value of Count does not increase. Similarly, when processing Thread Synchronization
Pay attention to the following issues:

Void somefunc ()

{

Lock (somemutex); // Add a lock

Delete P;

P = new someclass ();

Unlock (somemutex );

}

At this time, if new fails, unlock will not be executed, so it will not only cause a pointer pointing to an incorrect address
The existence of p will also cause someMutex to never be unlocked. This situation should be avoided. (Reference: C ++
Statement: code for exception Security)

STL memory allocation and traits skills

In the STL original code analysis book, the behavior of the memory distributor of sgi stl is analyzed in detail. Use new
Different from operator, sgi stl does not rely on C ++'s default memory allocation method, but uses a self-implemented solution. First, SGI
STL allocates the entire available memory block to make it available to the current process. When the program really needs to allocate memory, it first tries to get the memory from these large memory blocks that have been requested, try again if it fails.
The entire block is allocated with large memory. This method effectively avoids the emergence of a large number of memory fragments and improves the memory management efficiency.

To achieve this, STL uses placement
New: creates an object by using placement new in the memory space managed by the user to achieve the functions of the original new operator.

Template <class T1, class T2>

Inline void construct (T1 * p, const T2 &
Value)

{

New (p) T1 (value );

}

This function receives a constructed object and creates a new object on the given memory address p through copy construction. The Code
The last half of T1 (value) is placement.
The method for calling constructor in the new syntax. If the input object value is the required Type T1, it is equivalent to calling the copy constructor.

Reprinted

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.