安置新签名

时间:2012-01-22 14:07:56

标签: c++

 void someCode()
 {
   char memory[sizeof(Foo)];     
   void* place = memory;          

   Foo* f = new(place) Foo();
 }

以及新展示位置运算符的签名

void * operator new(size_t, void *p)
{
  return p;
}

我不知道构造函数如何绑定到void * p,因为构造函数不返回任何值?

修改 例如,以下代码无法编译:

struct A{};

void f(void * p)
{
}


int main()
{ 
    f(A());

  std::cin.ignore();
}

3 个答案:

答案 0 :(得分:5)

这里的问题是C ++ new令人困惑:

  • operator new,您可以重载并负责分配原始内存
  • new表达式(例如new A(5)),它首先调用相应的operator new重载,然后执行构建

请注意,您没有说明如何执行构造:您提供了类型和构造函数参数,语言完成了其余工作,并且无法更改此行为。

因此,当您重载/覆盖operator new时,您只会影响原始内存分配。 new表达式的完整语法可以解决问题:

new (somepointer) A(5)
    ^~~~~~~~~~~~~ ^~~~

第一部分是传递给对象大小的顶部的operator new的参数列表(总是传递)。第二部分对应于构造函数调用。如果没有参数传递给new(除了你不能控制的大小),那么第一部分可能会被省略,产生典型的new A(5)形式。

您可以根据需要自由地重载new,例如:

new (alignof(A)) A(5);

将调用operator new重载,接受size_t作为补充参数(表示该类型的必要对齐方式):

void* operator new(size_t size, size_t alignment);

注意:第一个参数(大小)始终存在。

所以,贴牌新品本身就是一种奇特的超载:

void* operator new(size_t, void* p) { return p; }

对这样的运算符没什么兴趣(它什么都不做),但它有助于维护一致的语法,并允许您通过使用new表达式来指定构建对象的位置,以便它是没有必要创建另一种语法来允许这样的操作。

答案 1 :(得分:2)

在operator new执行后调用的构造函数。您发布的不是等效代码。等价的是

struct A
{
    constructor (void* this);
}

int main ()
{
   A a = A::constructor(operator new ());
}

不是c++,只是pceudocode

答案 2 :(得分:2)

我认为你混淆的根源是假设new(place) Foo();是单一操作;它不是。这是正在发生的事情:

  • 调用placement new运算符来分配内存
  • 调用构造函数来初始化已分配的内存

第一个调用需要返回值(void*)。它是一个适合存储对象的内存块。第二个调用是构造函数。它将placement new运算符的值作为其隐藏的this参数获取,并在其上执行常规初始化任务。