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();
}
答案 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();
是单一操作;它不是。这是正在发生的事情:
第一个调用需要返回值(void*
)。它是一个适合存储对象的内存块。第二个调用是构造函数。它将placement new运算符的值作为其隐藏的this
参数获取,并在其上执行常规初始化任务。