关于Class的数组和新运算符用法的C ++语法

时间:2012-11-04 12:19:37

标签: c++ syntax operator-keyword

我的问题是关于来自Scott Meyer的书“更有效的C ++ 35新方法......”的代码snanpshot。

代码(参数名称已更改)

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);
}

我不熟悉这种语法。甚至运算符new []和new(&amp; myArray [i])...是否有任何资源我可以详细了解该语法,它们是如何工作的。

4 个答案:

答案 0 :(得分:2)

void * memory = operator new[] (10*sizeOf(MyClass));

这里分配大小为10*sizeOf(MyClass)个字节的内存。这是原始未初始化的内存。在这个内存中没有构造C ++对象。

new (&myArray[i]) MyClass(params);

在这里,您使用 placement-new &myArray[i]指向的给定内存中构造一个对象。

placement-new的典型语法是:

X * x = new (pAllocatedMem) X(a,b,c);

这意味着,您构造了一个X类型的对象,将abc传递给构造函数。该对象是在pAllocatedMem指向的内存中构造的。

另请注意,您删除了使用placement-new构建的对象,如:

x->~X(); //delete the constructed object. DONT USE : delete x;

也就是说,您没有delete x删除此类对象。

答案 1 :(得分:2)

维基百科将回答您的问题。

第一个new用于分配原始内存。

http://en.wikipedia.org/wiki/New_(C%2B%2B)#void.2A_operator_new.28size_t_size.29

  

仅分配内存的C ++语言构造称为void * operator new(size_t size)。它在分配阶段由new使用。可以为每个类重写它以定义特定于类的内存分配器。


第二个new称为展示位置。

http://en.wikipedia.org/wiki/Placement_new

  

使用附加void *参数的operator new和operator delete的放置重载用于默认放置,也称为指针放置。

答案 2 :(得分:2)

要理解这一点,首先需要了解简单new的工作原理。 new表达式的通常语法类似于new T。使用new表达式时,会发生以下情况:

  1. 首先,它调用分配函数来获取对象的存储空间。分配函数只需返回一个指向某个已分配存储的指针,该指针足够大以适合所请求的对象。它只不过是这个。它不会初始化对象。

  2. 接下来,在分配的空间中初始化对象。

  3. 返回指向已分配空间(现在已初始化的对象)的指针。

  4. new T的情况下,分配函数名为operator new。分配数组(例如new T[5])时,分配函数名为operator new[]。全局命名空间中提供了这些函数的缺省定义。它们各自采用类型std::size_t的单个参数,这是所需的字节数。因此,当您执行new T时,相应的调用将发送到operator new(sizeof(T)),而new T[5]则调用operator new[](sizeof(T)*5)

    但是,可以将更多参数传递给分配函数。这称为 placement new 语法。要传递更多参数,请使用如下语法:new (some, arguments, 3) T,它将调用operator new(sizeof(T), some, arguments, 3)。参数列表位于new和类型之间的括号中。

    除了由实现提供的简单operator new(std::size_t)及其数组副本之外,还有一些默认定义采用类型void*的额外参数。也就是说,它们采用指向对象的指针。这些函数实际上并没有分配任何空间,只是返回你给它们的指针。因此,当您执行new (some_pointer) T时,它首先调用operator new(sizeof(T), some_pointer),然后再次返回some_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*将转换为MyClass*,以允许您将大小为sizeof(MyClass)的块中的已分配存储编入索引,即myArray[0]现在将指向第一个MyClassmyArray[1]到第二个。

    现在我们循环遍历该数组,使用每个未初始化MyClass大小的已分配存储空间的地址调用 placement new 。例如,在第一次迭代中,这将调用分配函数operator new(sizeof(MyClass), &myArray[0]),正如我们之前看到的那样,它只会返回你给它的指针。新表达式将通过初始化此空间中的MyClass对象并将指针返回给它来完成。

    总而言之,代码分配一些存储空间以适应10 MyClass个对象(但不初始化它们),然后循环遍历该存储中的每个MyClass大小的空间,初始化一个对象他们每个人。

    这演示了如何在已预先分配的存储中初始化对象。您可以使用新初始化的对象重复使用相同的存储。

答案 3 :(得分:1)

new (&myArray[i]) MyClass(params);

展示位置new 运算符。它允许您在预先分配的内存位置创建对象。

18.4.1.3展示位置

  

void * operator new(std :: size_t size,void * ptr)throw();

     

返回:ptr。
  3注意:故意不执行任何其他操作   4 [示例:这对于在已知地址构造对象非常有用:

void* place = operator new(sizeof(Something));

Something* p = new (place) Something();
—end example]

void* operator new[](std::size_t size, void* ptr) throw();

5 Returns: ptr.
6 Notes: Intentionally performs no other action.