【问题标题】:Why does placement-new call the standard placement operator new function?为什么placement-new 调用标准的placement operator new 函数?
【发布时间】:2021-08-31 19:15:22
【问题描述】:

带有单个参数的placement-new 表达式将在该内存中构造一个T 类型的对象。

为什么它调用标准的placement-new 运算符void* operator new ( std::size_t count, void* ptr );,因为后者什么都不做,只返回它的指针参数?

 int x = 10;
 int* p = new(&x) int{1024};
  • 您能解释一下编译器在上面采取的步骤,在x的内存地址中构造一个新的int吗?

  • 为什么placement-new 表达式不直接在它作为指针获得的内存地址处构造一个对象,而不是调用一个什么都不做只返回其指针参数的操作符函数?

【问题讨论】:

  • new operators 可以在用户代码中重载/替换。这就是new 表达式 调用new 运算符 的原因。默认的placement-new operator 只返回它给出的指针。用户定义的placement-new operator 可以做任何它想做的事情(记录等),只要它仍然返回相同的指针。

标签: c++ placement-new


【解决方案1】:

一般规则是new (args...) T会调用operator new(sizeof(T), args...),这个函数需要返回void*。如果这个operator new调用成功返回,则将该对象构造到返回值指向的内存中。

这个通用规则足够强大,可以支持普通的新表达式new int和放置形式new (&x) int,没有任何特殊情况。这两个表达式调用operator new 的不同重载,这就是为什么前者分配而后者不分配的原因。无论如何,最后都会构造一个对象(除非operator new 函数因抛出异常而失败)。

没有必要在语言中设置一个特殊规则,即 operator new 不被放置新表达式调用。相反,编译器可以通过直接将int 对象构造为&x 来优化代码,而无需首先调用operator new,因为它已经知道放置operator new 只会返回其第二个参数。

(其实实际情况比这复杂一点。如果T是数组类型,那么operator new[]被调用而不是operator new,编译器可能会从operator new[]请求更多的内存比数组实际占用的内存大,在构造数组之前调整返回的指针。还有一些关于过度对齐类型的特殊规则,实际上还有一些特殊情况的放置new和delete。这些细节与这个答案。)

【讨论】:

  • "编译器可以通过直接将int 对象构造成&x 来简单地优化代码,而无需首先调用operator new,因为它已经知道放置operator new 将只是返回它的第二个参数" - 你确定吗?那么operator new在用户代码中被重载的情况呢?编译器不能/不应该优化它。
  • @RemyLebeau 全局placement operator new 不允许被覆盖。
猜你喜欢
  • 2021-08-22
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多