所以我最近遇到了新的位置,我有一个问题。我知道当你想在已经分配的内存上分配一个对象时,会使用placement new。
假设我有一个名为foo的类,它是20个字节。
我会用它做一些操作,然后我会为一个名为bar的类调用一个新的位置,这是10个字节。
不属于新对象的最后10个字节会发生什么?放置新分区只需要所需的内存量,在这种情况下是10个字节吗?或者指针只是携带额外的10个字节,直到它被解除分配?
另一种情况,假设我首先开始为类别栏分配内存,这是10个字节。然后我将放置新的类foo,即20个字节。编译器会分配更多内存吗?或者我必须事先确保分配足够的内存吗?
答案 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只是在您提供的内存地址上构造指定的类。您有责任确保内存足够大以容纳正在构建的类。
或者我必须事先确定分配足够的内存吗?
是