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

时间:2015-08-14 00:51:10

标签: c++ placement-new

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

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

我会用它做一些操作,然后我会为一个名为bar的类调用一个新的位置,这是10个字节。

不属于新对象的最后10个字节会发生什么?放置新分区只需要所需的内存量,在这种情况下是10个字节吗?或者指针只是携带额外的10个字节,直到它被解除分配?

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

2 个答案:

答案 0 :(得分:1)

  

不属于新对象的最后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;
  

另一种情况,让我说我首先开始为类吧分配内存,这是10个字节。然后我将放置新的类foo,即20个字节。编译器会分配更多内存吗?

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

答案 1 :(得分:1)

  

不属于新对象的最后10个字节会发生什么。

什么都没有。 Placement-new不接触它。它不知道该内存块中是否还存在其他东西。您可以轻松地为2 bar个对象分配大小,在后10个字节中构造bar对象,然后在前10个字节中构造另一个bar对象。想想如果placement-new做了一些事情来超越你提供的内存地址的边界会发生什么,它会破坏内存后半部分的bar。不好。所以它没有这样做。

  

放置新分区是否只需要所需的内存量,在这种情况下是10bytes?

是。 Placement-new将简单地调用bar构造函数,将指定的内存地址作为初始化构造函数的起始地址传递给它。构造函数只会初始化它所需的内存部分。由于bar类是10个字节,因此可以初始化不超过10个字节。剩余的10个字节不受影响。

  

或者指针只是携带额外的10个字节,直到它被解除分配。

如果在前10个字节中分配20个字节并构造bar,则剩余的10个字节将仅存在于内存中的bar对象之后,但不属于{{1}对象本身。你可以用这10个字节做任何你想做的事。

  

另一种情况,让我说我首先开始为类吧分配内存,这是10个字节。然后我将放置新的类foo,即20个字节。编译器会分配更多内存吗?

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

  

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