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的函数来分配具有我所需属性的内存(例如从哪个内存库,缓存在哪里等等)
首先,让我们确保大家都同意内存分配和对象构建的分离.考虑到这一点,让我们假设我们有足够的内存用于对象数组:
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)