Placement new operator __c++ in C + +

Source: Internet
Author: User

Placement new is a standard, global version of the overloaded operator new, which cannot be replaced by a custom version (unlike normal operator new and operator delete can be replaced with a user-defined version).

Its prototype is as follows:

void *operator new (size_t, void *p) throw () {return p;}

First we distinguish the next few easy to confuse keywords: new, operator new, placement new

The new and delete operators should all be used, which is to request and release the memory in the heap, both of which cannot be overloaded. To implement different memory allocation behaviors, you need to overload operator new instead of new and delete.

Look at the following code:

Class MyClass {...};

MyClass * P=new MyClass;

The new here is actually performing the following 3 procedures:

1 call operator new to allocate memory;

2 invokes the constructor to generate the class object;

3 returns the corresponding pointer.

operator new, like operator+, can be overloaded, but it cannot be overloaded globally with a prototype of void operator new (size_t size), which can generally only be overloaded in a class. If there is no overload operator new in the class, then the call is global:: operator new to complete the heap allocation. Similarly, operator new[], operator delete, operator delete[] can also be overloaded, generally you overload one of them, then it is best to overload the remaining three.

Placement New is an overloaded version of operator new, but we rarely use it. If you want to create an object in an already allocated memory, it is not possible to use new. In other words, placement new allows you to construct an object in an already allocated memory (stack or heap). The void*p in the prototype is actually the first address that points to a allocated memory buffer.

We know that using the new operator to allocate memory requires looking for enough space in the heap, which is slow, and it is possible to have an exception that cannot allocate memory (not enough space). Placement new can solve this problem. We construct objects in a prepared memory buffer, do not need to find memory, memory allocation time is constant, and there is no out-of-memory exception in the middle of the program run. Therefore, placement new is ideal for applications that have high time requirements and do not want to be interrupted for long periods of time.

Use the following methods:

1. Buffer Advance allocation

You can use the space of the heap, or you can use the space of the stack, so there are two ways to allocate it:

Class MyClass {...};
Char *buf=new char[n*sizeof (MyClass) + sizeof (int)]; or char buf[n*sizeof (MyClass) + sizeof (int)];

2. Construction of objects

MyClass * Pclass=new (BUF) MyClass;

3. Destruction of objects

Once this object is used, you must explicitly invoke the class's destructor to destroy the object. However, the memory space is not freed so that other objects are constructed.

Pclass->~myclass ();

4. Release of Memory

If the buffer is in the heap, then the delete[] buf is invoked, the memory is freed, and if it is in the stack, it is active within its scope, and the memory is automatically released.

Attention:

1 in the C + + standard, for placement operator new [] like the following description: placement operator new[] needs implementation-defined amount of Addit ional Storage to save a size of array. So we have to apply sizeof (int) bytes more than the original object size to hold the number of objects, or the size of the array.

2 Use method The new in the second step is placement new, in fact, there is no application memory, just called the constructor, returns a pointer to the allocated memory, so the object is destroyed without calling delete free space, but the destructor must be called to destroy the object.

--------------------------------------------------------------------------------------------------------------- --explicit invocation of constructors and destructors

Chatting with colleagues today, he said that STL source is useful to display call destructor. Give it a try. Sure enough.

Results:

Constructors

Destructors//This is the destructor of the display call

Destructors//This is the destructor of the delete call

What's the use?

Sometimes it's useful to end this object before the end of the object's lifecycle.

the thought of this:

Because I know.

New, actually do two things, one is: Call malloc allocate the required memory, the second is: Call the constructor.

Delete, but also do two things, one is: Invoke the destructor, the second is: Call free freed memory.

So presumably constructors can be called explicitly as well. Made a realization.

int _tmain (int argc, _tchar* argv[])
{
    myclass* pmyclass = (myclass*) malloc (sizeof (MyClass));
     Pmyclass->myclass ();
    ..
}

Error compiling Pmyclass->myclass ():

Error C2273: ' Function-style cast ': illegal as right side of '-> ' operator

God, it thought MyClass was this type.

There are two solutions:

First: Pmyclass->myclass::myclass ();
Second: New (Pmyclass) MyClass ();

The second usage involves the use of C + + placement new.

The role of placement new is to create an object (calling the constructor of the class) but not to allocate memory, but to create an object on an existing block of memory. For objects that need to be created and deleted repeatedly, you can reduce the performance cost of allocating freed memory. Please refer to placement new information.

shows what is the use of calling the constructor.

Sometimes you might want to use malloc to allocate memory to a class object because of the efficiency, because malloc is not calling the constructor, so this time will come in handy.

The following is also possible, although built-in types do not have constructors.

int* i = (int*) malloc (sizeof (int));
New (i) int ();

It feels like these weird usages are best used when writing code base, in order to reach an aim, not recommended for application development.

#include <iostream>
usingnamespace std;

Class MyClass
{public
:
    MyClass ()
    {
        cout << "constructors" << Endl;
    }
    ~myclass ()
    {
        cout << "destructors" << Endl;
    }

};

int _tmain (int argc, _tchar* argv[]) {myclass* pmyclass =new
   ;
   Pmyclass->~myclass ();
   Delete pmyclass;

}
new, operator new and placement New in C + +

New/delete and operator New/operator Delete in C + +

The new Operator/delete operator is the new and delete operator, and operator New/operator Delete is a function.

New operator
(1) Call operator new to allocate enough space and call the constructor of the related object
(2) can not be overloaded

operator NEW
(1) Allocate only the required space and do not invoke the constructor of the related object. When the required allocated space is not met, the
-> If there is a new_handler, call New_handler, otherwise
-> If there is no requirement not to throw an exception (expressed as a nothrow parameter), then the bad_alloc exception is executed, otherwise
-> return 0
(2) can be overloaded
(3) When overloaded, the return type must be declared as void*
(4) When overloaded, the first parameter type must be the size (in bytes) of the expression requirement allocation space, and the type is size_t
(5) When overloaded, can take other parameters

Delete is similar to the delete operator

#include <iostream>
#include <string>
using namespace std;

Class X
{public
:
    x () {cout<< "constructor of X" <<endl;}
    ~x () {cout<< "destructor of X" <<ENDL;}

    void* operator new (size_t size,string str)
    {
        cout<< "operator new size" <<size<< "with string" <<str<<endl;
        Return:: operator new (size);
    }

    void operator Delete (void* pointee)
    {
        cout<< operator delete <<endl;
        :: operator Delete ( pointee);
    }
Private:
    int num;
};

int main ()
{
    x *px = new ("A new Class") x;
    Delete px;

    return 0;
}

x* px = new X; The new in the line code is new operator, which calls the operator new in class X, allocates space for objects of that class, and then calls the constructor of the current instance.
Delete px; The delete in the line code is the delete operator, which calls the destructor of the instance, and then calls the operator delete in class X to free up the space occupied by the instance.

The behavior of the new operator and delete operator cannot and should not be changed, which is the commitment of the C + + standard. The operator new and the malloc in the operator delete and C languages correspond to free, which is responsible for allocating and releasing space only. However, the space allocated using operator new must be freed using the operator delete, not free, because they are registered differently for memory usage. The reverse is also the same. You can overload operator new and operator Delete to achieve different requirements for memory management, but you cannot overload the new operator or delete operator to change their behavior.

Why it is necessary to write your own operator new and operator delete.
The answer is usually: for efficiency. The default operator new and operator Delete are very versatile, and this flexibility makes it possible to further improve its performance in certain situations. This is especially true in applications that need to dynamically allocate large but small objects. Specific reference to the "effective C + +" in chapter II memory management.

The meaning of placement new

Placement new is a standard, global version of the overloaded operator new that cannot be replaced by a custom version (unlike the normal version of operator new AND operator delete).

void *operator new (size_t, void * p) throw () {return p;}

The execution of placement new ignores the size_t parameter and returns only the second argument. The result is that the user is allowed to put an object in a specific place and achieve the effect of calling the constructor. Unlike other ordinary new, it has another argument in parentheses. Like what:

Widget * p = new Widget; Ordinary New

PI = new (ptr) int;     PI = new (ptr) int; Placement NEW

The parameter ptr in parentheses is a pointer to a memory buffer in which placement new assigns an object to the buffer. The return value of placement new is the address of the constructed object (such as the passing parameter in parentheses). Placement new is primarily useful in applications that are very demanding in time, because the time that these programs are assigned is determined, the programs that run long hours without interruption, and the execution of a garbage collector (garbage collector).

New, operator new and placement new difference

(1) NEW: cannot be overloaded, its behavior is always the same. It first calls operator new to allocate memory, and then calls the constructor to initialize that memory.

The execution process of the new operator:
1. Call operator new to allocate memory;
2. Call constructor to generate class object;
3. Return the corresponding pointer.

(2) operator NEW: To implement different memory allocation behavior, you should overload operator new instead of new.

operator new, like Operator +, can be overloaded. If there is no overload operator new in the class, then the call is global:: operator new to complete the heap allocation. Similarly, operator new[], operator delete, operator delete[] can also be overloaded.

(3) Placement NEW: Just a version of operator new overload. It does not allocate memory, but simply returns a pointer to a segment of memory that has been allocated. Therefore, you cannot delete it, but you need to invoke the destructor of the object.

If you want to create an object in the allocated memory, it won't work when you use new. In other words, placement new allows you to construct an object in an already allocated memory (stack or heap). The void* p in the prototype is actually the first address that points to an already allocated memory buffer.

Placement the reason for the new existence

1. Solve the problem of buffer with placement new

Problem Description: When array buffering is allocated with new, execution is inefficient because the default constructor is invoked. A compile-time error occurs if there is no default constructor. If you want to create an object on a pre-configured memory, it won't work with the default new operator. To solve this problem, you can use placement new constructs. It allows you to construct a new object into the preconfigured memory.

2. Increase the time and space efficiency problem

allocating memory using the new operator requires looking for a large enough amount of space in the heap, which is obviously slow, and there may be an exception (not enough space) to allocate memory. Placement new can solve this problem. We construct objects in a prepared memory buffer, do not need to find memory, memory allocation time is constant, and there is no out-of-memory exception in the middle of the program run. Therefore, placement new is ideal for applications that have high time requirements and do not want to be interrupted for long periods of time.

Placement new Use steps

In many cases, the use of placement new is different from other ordinary new. The steps to use it are provided here.

First step cache advance allocation

There are three different ways:

1. To ensure that the memory alignment (memory queue) of the buffer used by placement new is properly prepared, use the normal new to allocate it: allocate on the heap
Class Task;
char * buff = new [sizeof (Task)]; Allocating memory
(Note that auto or static memory is not all aligned correctly for each object type, so you won't be able to use them with placement new.) )

2. Distribute on the stack
Class Task;
Char buf[n*sizeof (Task)]; Allocating memory

3. Another way is to use the address directly. (Must be a meaningful address)
void* buf = reinterpret_cast<void*> (0xf00f);

Step Two: Assignment of objects

Call placement new to construct an object in the cache that has just been allocated.
Task *ptask = new (BUF) task

Step Three: Use

Use assigned objects in the normal way:

Ptask->memberfunction ();

Ptask-> member;

//...

Fourth step: The Deconstruction of objects

Once you have finished using this object, you must call its destructor to destroy it. Call the destructor in the following way:
Ptask->~task (); Calling an external destructor

Step Fifth: Release

You can reuse the cache and assign it a new object (Repeat step 2,3,4) If you do not intend to use the cache again, you can release it like this: delete [] buf;

Skipping any step can lead to runtime crashes, memory leaks, and other unexpected scenarios. If you really need to use placement new, please follow these steps carefully.

#include <iostream>
using namespace std;

Class X
{public
:
    x () {cout<< "constructor of X" <<endl;}
    ~x () {cout<< "destructor of X" <<ENDL;}

    void Setnum (int n)
    {
        num = n;
    }

    int Getnum ()
    {return
        num;
    }

Private:
    int num;
};

int main ()
{
    char* buf = new char[sizeof (X)];
    X *px = new (BUF) x;
    Px->setnum (ten);
    Cout<<px->getnum () <<endl;
    Px->~x ();
    delete []buf;

    return 0;
}

Related Article

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.