这第二个新的是什么?

发布于 2024-09-28 03:29:03 字数 167 浏览 5 评论 0原文

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

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

第二行之后 x 和 y 具有相同的值(指向相同的位置)。 y = x 和第二行有什么区别?它像构造函数还是什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

女皇必胜 2024-10-05 03:29:03

这是新展示位置。它在x指向的内存中构造一个新的int

如果您尝试:

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

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
趁年轻赶紧闹 2024-10-05 03:29:03

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.

空心↖ 2024-10-05 03:29:03

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

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.

oО清风挽发oО 2024-10-05 03:29:03

这是新的安置。

尽管您通常不将它与整数类型一起使用。
它通常用于构建一个缓冲区,然后在其中构建其他类型。

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

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

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

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

delete [] buffer;

其他一些注意事项:
人们经常看到缓冲区可以在堆栈上实现,从而自动释放,

char buffer[sizeof(T) * 2];

不幸的是这在技术上可能是可以的(它可以编译)。但不能保证它能正常工作,因为缓冲区的内存可能无法正确对齐,无法将 T 放入其中。因此,您必须动态分配缓冲区(通过使用 new 它可以保证内存对于分配的大小的任何对象正确对齐(因此通过扩展,它也可以针对小于分配的大小的任何大小进行对齐)。这个问题是使用 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.

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

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).

哥,最终变帅啦 2024-10-05 03:29:03
int * y = new (x) int; 

这是根据放置新语法。

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

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 不分配内存,它在括号中指定的地址构造对象。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文