采用单个参数的 placement-new
表达式将在该内存中构造一个 T
类型的对象。
为什么它调用标准的 placement-new
运算符 void* operator new ( std::size_t count, void* ptr );
,因为后者什么都不做,只是返回它的指针参数?
int x = 10;
int* p = new(&x) int{1024};
你能解释一下编译器在上面的步骤中在int
的内存地址中构造一个新的x
吗?
为什么 placement-new
表达式不直接在它作为指针获取的内存地址处构造一个对象,而不是调用一个什么都不做只返回其指针参数的操作符函数?
答案 0 :(得分:1)
一般规则是new (args...) T
会调用operator new(sizeof(T), args...)
,这个函数需要返回void*
。如果此 operator new
调用成功返回,则将对象构造到返回值指向的内存中。
这个通用规则足够强大,无需任何特殊情况即可支持普通的 new 表达式 new int
和展示位置形式 new (&x) int
。这两个表达式调用了不同的 operator new
重载,这就是为什么前者分配而后者不分配的原因。不管怎样,最后都会构造一个对象(除非 operator new
函数因抛出异常而失败)。
没有必要在语言中设置一条特殊规则,说明 operator new
不被展示位置 new 表达式调用。相反,编译器可以通过直接将 int
对象构建到 &x
中而不先调用 operator new
来简单地优化代码,因为它已经知道位置 operator new
将只返回其第二个论点。
(实际上,实际情况比这要复杂一些。如果T
是数组类型,则调用operator new[]
而不是operator new
,编译器可能会从{ {1}} 比数组实际占用更多的内存,并在构造数组之前调整返回的指针。还有与过度对齐类型相关的特殊规则,实际上还有一些特殊情况用于放置 new 和删除。这些详细信息与此答案无关。)