使用C++的"placement new"进行动态分配

tow*_*ism 2 c++ malloc placement-new dynamic-arrays

问题:如何使用" placement new "创建动态大小的数组?或者更具体地说,如何从预先分配的存储器中为数组元素分配存储器.

我使用以下代码:

void* void_array = malloc(sizeof(Int)); 
Int* final_array = new(void_array) Int;
Run Code Online (Sandbox Code Playgroud)

这保证了final_array*(数组指针)是从void_array*保留的位置分配的.但是final_array元素呢?我希望它们也可以从预先分配的内存中分配.

PS:我不得不说我正在使用一些API来给我一些控制瓦片架构.有一个函数与malloc完全相同,但也有其他功能,例如,让您控制分配的内存的属性.所以,我基本上需要做的是,使用类似malloc的函数来分配具有我所需属性的内存(例如从哪个内存库,缓存在哪里等等)

Ker*_* SB 6

首先,让我们确保大家都同意内存分配和对象构建的分离.考虑到这一点,让我们假设我们有足够的内存用于对象数组:

void * mem = std::malloc(sizeof(Foo) * N);
Run Code Online (Sandbox Code Playgroud)

现在,您无法使用placement array-new,因为它已被破坏.正确的做法是分别构造每个元素:

for (std::size_t i = 0; i != N; ++i)
{
    new (static_cast<Foo*>(mem) + i) Foo;
}
Run Code Online (Sandbox Code Playgroud)

(只有指针算术才需要强制转换.place-new所需的实际指针只是一个void指针.)

顺便说一下,这正是标准库容器的工作方式,以及标准库分配器的设计方式.关键是你已经知道了元素的数量,因为你在初始内存分配中使用了它.因此,您不需要C++数组提供的魔力new,这就是在某处存储数组大小并调用构造函数和析构函数.

销毁工作相反:

for (std::size_t i = 0; i != N; ++i)
{
    (static_cast<Foo*>(mem) + i)->~Foo();
}

std::free(mem);
Run Code Online (Sandbox Code Playgroud)

不过,您必须了解的另一件事是:异常安全.除非Foo有一个没有抛出的构造函数,否则上面的代码实际上是不正确的.要正确编码,您还必须存储展开位置:

std::size_t cur = 0;
try
{
    for (std::size_t i = 0; i != N; ++i, ++cur)
    {
        new (static_cast<Foo*>(mem) + i) Foo;
    }
}
catch (...)
{
    for (std::size_t i = 0; i != cur; ++i)
    {
        (static_cast<Foo*>(mem) + i)->~Foo();
    }
    throw;
}
Run Code Online (Sandbox Code Playgroud)

  • @TOWI_Parallelism:阅读[链接问题](http://stackoverflow.com/q/8720425/596781).细节是技术性和无聊的,对于这个评论来说太长了.请相信我的话.相信我,我是一条鱼.(或者在聊天室里问一下!) (2认同)