在不同大小的类上放置新的位置

Placement new on a different size class

本文关键字:位置      更新时间:2023-10-16

所以我最近遇到了新的安置,我有一个关于它的问题。当你想在已经分配的内存上分配对象时,可以使用位置new。

假设我有一个名为foo的类,它有20个字节。

我将对它做一些操作,然后我将为一个名为bar的类调用放置new,它有10个字节。

不属于新对象的最后10个字节会发生什么?放置新分区是否只需要所需的内存量,在本例中是10字节?或者指针只是携带额外的10字节,直到它被释放?

另一种情况,假设我首先为类bar分配了10个字节的内存。然后我将放置新的类foo,这是20个字节。编译器会分配更多内存吗?或者我必须确保事先分配足够的内存吗?

不属于新对象的最后10个字节怎么办

什么都没有。放置-新不触及它。它不知道那个内存块中是否已经存在其他东西。您可以轻松地为2个bar对象分配大小,在第二个10个字节中构造一个bar对象,然后在前10个字节中构造另一个bar对象。想象一下,如果place -new做了一些事情,超出了您提供的内存地址的范围,并且损坏了内存的后半部分的bar,将会发生什么。不好的。所以它不会那样做

放置新分区是否只需要所需的内存量,在本例中是10字节?

是的。Placement-new只需调用bar构造函数,将指定的内存地址传递给它,作为构造函数初始化的起始地址。构造函数只初始化它需要的那部分内存。由于bar类是10个字节,因此初始化的字节不能超过10个字节。

或者指针只携带额外的10字节,直到它被释放。

如果分配20个字节并在前10个字节中构造一个bar,那么剩余的10个字节将存在于内存中的bar对象之后,而不是bar对象本身的一部分。你可以用这10个字节做任何你想做的事。

另一种情况,假设我首先为类bar分配了10个字节的内存。然后我将放置新的类foo,这是20个字节。编译器会分配更多内存吗?

。placementnew只是在您提供的内存地址上构造指定的类。你有责任确保内存足够大以容纳正在构造的类。

或者我必须确保事先分配足够的内存?

是的。

不属于新对象的最后10个字节怎么办

这些额外的字节仍然可供您使用。只有使用正确的解分配方法,它们才会被正确地解分配。

// Allocate memory.
char* buffer = new char[20];
// Construct a Foo using placement new
Foo* fooPtr = new (buffer) Foo;
// Use fooPtr
// ...
// Call the destructor for fooPtr explicitly.
// Don't call delete fooPtr. That will lead to
// undefined behavior.
fooPtr->~Foo();
// Now the memory is ready to be resued.
// Construct a Bar using placement new
Bar* barPtr1 = new (buffer) Bar;
// If there is enough space, you can use:
Bar* barPtr2 = new (buffer+sizeof(Bar)) Bar;
// Use barPtr1 and barPtr2
// ...
// Now call the destructor on the pointers explicitly.
barPtr1->~Bar();
barPtr2->~Bar();
// Deallocate the memory that corresponds to the method used to
// allocate it.
delete [] buffer;

另一种情况,假设我首先为类bar分配了10个字节的内存。然后我将放置新的类foo,这是20个字节。编译器会分配更多内存吗?

不,编译器不会分配更多的内存。这将导致未定义的行为