要理解这一点,您首先需要了解简单明了的new工作原理。表达式的常用语法new类似于new T. 使用new表达式时,会发生以下情况:
首先,它调用分配函数来获取对象的存储空间。分配函数只需返回一个指针,该指针指向某个已分配的存储空间,该存储空间足够大以适合所请求的对象。它仅此而已。它不会初始化对象。
接下来,在分配的空间中初始化对象。
返回指向已分配空间(以及现在已初始化的对象)的指针。
在 的情况下new T,分配函数被命名为operator new。分配数组时,如new T[5],分配函数名为operator new[]。这些函数的默认定义在全局命名空间中提供。它们每个都采用一个类型的参数,std::size_t即所需的字节数。因此,当您这样做时new T,相应的调用是 to ,operator new(sizeof(T))而 for被调用。new T[5]operator new[](sizeof(T)*5)
但是,可以将更多参数传递给分配函数。这称为放置新语法。要传递更多参数,您可以使用如下语法:new (some, arguments, 3) T,它将调用operator new(sizeof(T), some, arguments, 3). 参数列表放在new和类型之间的括号中。
除了operator new(std::size_t)由实现提供的 simple 及其对应的数组之外,还有一些默认定义采用额外的 type 参数void*。也就是说,它们采用指向对象的指针。这些函数实际上并不分配任何空间,而只是返回您给它们的指针。因此,当您这样做时new (some_pointer) T,它首先调用operator new(sizeof(T), some_pointer)whichsome_pointer再次返回,然后初始化该空间中的对象。这为您提供了一种在某些已分配空间中初始化对象的方法。
所以现在我们有了这四个预定义的分配函数(事实上,还有一些其他的,你也可以自由定义自己的):
// Normal allocation functions that allocate space of the given size
operator new(std::size_t)
operator new[](std::size_t)
// Placement allocation functions that just return the pointer they're given
operator new(std::size_t, void*)
operator new[](std::size_t, void*)
因此,让我们看一下您提供的代码片段:
void * memory = operator new[] (10*sizeOf(MyClass));
MyClass * myArray = static_cast<MyClass*>(memory);
for(int i= 0; i<10; i++)
{
new (&myArray[i]) MyClass(params);
}
在第一行,我们operator new[]直接调用分配一些存储空间。多少存储空间?好吧,足以容纳 10 个类型的对象MyClass。此函数返回一个指向该分配存储的指针,并将其存储在memory.
在此之后,void*被强制转换为 aMyClass*以允许您以 size 的块索引分配的存储sizeof(MyClass),即myArray[0]现在将指向第一个MyClass 和myArray[1]第二个。
现在我们遍历该数组,调用placement new,并使用每个未初始化MyClass大小的已分配存储位的地址。例如,在第一次迭代中,这将调用分配函数operator new(sizeof(MyClass), &myArray[0]),正如我们之前看到的,它什么都不做,只是返回你给它的指针。新表达式将通过MyClass在这个空间中初始化一个对象并返回指向它的指针来完成。
所以总而言之,代码分配了一些存储空间来容纳 10 个MyClass对象(但不初始化它们),然后循环遍历MyClass该存储空间中的每个 -size 空间,在每个对象中初始化一个对象。
这演示了如何在已经预分配的存储中初始化对象。您可以对新初始化的对象反复重用相同的存储。