What is this second new?

醉酒当歌 提交于 2020-01-02 00:49:09

问题


What is the second line? (Seen while answering another question.)

int * x = new int [1] ;
int * y = new (x) int;

After the second line x and y have the same value (point to a same place). What's the difference between y = x and the second line? Is it like a constructor or something?


回答1:


It's placement new. It constructs a new int in the memory pointed to by x.

If you try:

int * x = new int [1];
*x = 5;
std::cout << *x << std::endl;
int * y = new (x) int;
*y = 7;
std::cout << *x << std::endl;

the output will be:

5
7



回答2:


This is called placement new. It allows you to construct an object in memory already allocated.

This earlier thread discusses where and how it is useful for.




回答3:


The second new is a "placement new". It performs initialization (i.e. call any necessary constructors) without doing any allocation. It is useful when you need to create a custom memory allocation scheme.




回答4:


This is placement new.

Though you don;t usually use it with integer types.
It is usually used to build a buffer where you then build other types into.

// Allocate a buffer with enough room for two T objects.
char* buffer   = new char[sizeof(T) * 2];

// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");

// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");

Thats the basics.
But remember that the objects allocated with placement new can not be deleted with the delete statement. This is because delete tries to reclaim memory allocated by new (as well as call the destructor). So to use these objects correctly you must manually call there destructor.

t1->~T();
t2->~T();

Don't forget to delete the original buffer.

delete [] buffer;

A few other caveats:
People often see that buffer could be implemented on the stack and thus be automatically freed

char buffer[sizeof(T) * 2];

Unfortunately this may be technically OK (It compiles). But it is not guaranteed to work as the memory of buffer may not be aligned correctly for a T to be placed inside. So you must allocate the buffer dynamically (by using new it gurantees that the memory is aligned correctly for any object of the size allocated (thus by extension it is also aligned for any size smaller then the size allocated). The easy way to get around this problem is to use a std::vector

std::vector<char>    buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");

Another use of placement new is to reset an object.
I have seen this done but I prefer to use the more standard assignment operator:

T   obj1("Plop");
obj1  = T("Another Plop");

// Can be done like this:
T   obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop");   // Seems excessive to me. But can be us-full
                                 // in some extreme situations.

Remember if you use the reset method you must destroy the old object first (or the object may not behave correctly).




回答5:


int * y = new (x) int; 

This is as per placement new syntax.

EDIT: Along with custom allocation, placement new also helps to re-initialze an object state like below.

class Test
{
    int startVal;
public:
    Test()
    {
        startVal = 1;
    }
    void setVal(int val) { startVal = val; }
};
int main()
{
    Test *p = new Test;  //Creates new object and initializes it with
                          //a call to constructor.
    p->setVal(10);  //Change object content.
    new(p) Test; //Reset object:
    //object pointed by p will be re-initialzed here by making
    //a call to constructor. startVal will be back to 1
}

As described in comments above, object state resetting also can be achieved using placement new. placement new doesn't allocate memory, it constructs object at the specified address in the paranthesis.



来源:https://stackoverflow.com/questions/3960548/what-is-this-second-new

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!