这第二个新内容是什么?

时间:2010-10-18 15:12:35

标签: c++ syntax terminology new-operator placement-new

第二行是什么? (在回答另一个问题时看到。)

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

在第二行之后,x和y具有相同的值(指向同一位置)。 y = x和第二行之间有什么区别?它是构造函数还是其他东西?

5 个答案:

答案 0 :(得分:13)

这是placement new。它在int指向的内存中构造一个新的x

如果您尝试:

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

输出将是:

5
7

答案 1 :(得分:4)

这称为placement new。它允许您在已经分配的内存中构造一个对象。

这个早期的主题讨论where and how it is useful for

答案 2 :(得分:3)

第二个新内容是“放置新”。它执行初始化(即调用任何必要的构造函数)而不进行任何分配。当您需要创建自定义内存分配方案时,它非常有用。

答案 3 :(得分:3)

这是新的展示位置。

虽然你不喜欢,但通常使用整数类型 它通常用于构建缓冲区,然后在其中构建其他类型。

// 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");

这是基础知识 但请记住,使用delete语句删除使用展示位置分配的对象 。这是因为delete尝试回收new分配的内存(以及调用析构函数)。因此,要正确使用这些对象,必须手动调用析构函数。

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

不要忘记删除原始缓冲区。

delete [] buffer;

其他一些警告:
人们经常看到缓冲区可以在堆栈上实现,因此可以自动释放

char buffer[sizeof(T) * 2];

不幸的是,这在技术上可能是正常的(它编译)。但是不能保证工作,因为缓冲区的内存可能无法正确对齐,以便将T放置在内部。因此,您必须动态分配缓冲区(通过使用新的保证,内存已正确对齐任何分配大小的对象(因此通过扩展,它也可以对齐任何小于分配大小的大小)。简单的方法来绕过这个问题是使用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");

放置new的另一个用途是重置一个对象 我已经看到了这个,但我更喜欢使用更标准的赋值运算符:

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.

请记住,如果使用重置方法,则必须首先销毁旧对象(否则对象可能无法正常运行)。

答案 4 :(得分:2)

int * y = new (x) int; 

这是根据展示位置的新语法。

编辑:除了自定义分配外,新位置还有助于重新初始化对象状态,如下所示。

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
}

如上面的评论中所述,也可以使用placement new来实现对象状态重置。 placement new不分配内存,它在paranthesis中的指定地址构造对象。