在预分配的内存中创建对象

9
我们可以使用定位new来在预分配的内存中创建一个对象。
让我们考虑以下示例:
char *buf  = new char[1000];   //pre-allocated buffer
string *p = new (buf) MyObject();  //placement new 
string *q = new (buf) MyObject();  //placement new

我已经在预先分配的缓冲区中创建了两个对象。这两个对象是随机创建在缓冲区内还是在连续的内存块中创建的?如果我们继续在缓冲区中创建更多的对象,并希望它们存储在连续的内存块中,我们应该怎么做呢?首先在缓冲区中创建一个数组,然后在数组的元素插槽中创建每个对象。


1
如果我们继续在缓冲区中创建更多对象,并希望它们存储在连续的内存块中,我们应该怎么做?使用std::vector,它是一个连续存储的动态数组。 - GManNickG
2个回答

8

两个对象都在同一个内存位置创建,即buf。这是未定义的行为(除非对象是POD)。

如果您想分配多个对象,则必须递增指针,例如buf + n * sizeof(MyObject),但要注意对齐问题。

还要记得在完成时调用析构函数。


1
因为缓冲区是使用 new 分配的,所以它具有对任何类型(包括数组)进行支持的对齐方式。(总的来说你并没有错,只是在这种情况下他是安全的。) - GManNickG
@GMan:谢谢,说得好。我想如果你想把不同类型的对象放入内存中,就需要额外注意。 - Kerrek SB
“Plain old data”指的是基本类型,或者是由POD组成的数组,或者是没有构造函数且只包含POD的类。任何仅由其二进制表示确定且可以进行内存复制的内容。 - Kerrek SB

5
以下代码行:
string *p = new(adr) MyObject();

将在地址adr处创建一个MyObject对象。下一次创建另一个对象时,您将知道adr处的内存正在被第一个对象使用,因此您的下一个对象必须创建在adr + sizeof(MyObject)处:

string *q = new(adr + sizeof(MyObject)) MyObject();

预分配内存的目的是为了避免在运行时进行分配,因为这样会很慢。您可以在循环/程序开始时进行一次大的分配,然后只需使用该分配的块即可。缺点是您必须管理自己的内存,这意味着您必须找到放置对象的位置,当内存池变得分散时,这变得棘手!


如果adr = static_cast<MyObject*>(byteaddr),那么你需要这样做:string *q = new(adr+1)MyObject(); - Roland Puntaier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接