当:: operator new足够时,为什么需要:: operator new []?

xml*_*lmx 23 c++ standards memory-management overloading new-operator

众所周知,C++标准定义了两种形式的全局分配函数:

void* operator new(size_t);
void* operator new[](size_t);
Run Code Online (Sandbox Code Playgroud)

而且,C++标准草案(18.6.1.2 n3797)说:

227)运算符new或operator delete不直接负责注意数组的重复次数或元素大小.这些操作在数组new和delete表达式的其他位置执行.但是,数组新表达式可以将operator参数增加到operator new以获得存储补充信息的空间.

让我困惑的是:

如果我们void* operator new[](size_t);从标准中删除,而只是使用该void* operator new(size_t)怎么办?定义冗余全局分配函数的基本原理是什么?

Pot*_*ter 12

我认为::operator new[]对于相当专业的系统可能是有用的,其中"大但很少"的阵列可能由不同的分配器分配,而不是"小而多"的对象.然而,它目前是一个遗物.

operator new可以合理地期望一个对象将在返回的确切地址处构建,但operator new[]不能.分配块的第一个字节可能用于大小"cookie",数组可能是稀疏初始化的,等等.区别对于成员来说更有意义operator new,它可能专门用于其特定的类.

在任何情况下,::operator new[]都不是非常必要的,因为std::vector(via std::allocator),这是目前最流行的获取动态数组的方法,忽略它.

在现代C++中,自定义分配器通常是比定制更好的选择operator new.实际上,new表达式应该完全避免使用容器(或智能指针等)类,这样可以提供更多的异常安全性.

  • 在我看来这是不正确的.见答案. (2认同)

dav*_*pfx 7

标准(n3936)清楚地表明这两个运营商服务于不同但相关的目的.

operator new调用该函数void* operator new(std::size_t).第一个参数必须与运算符的参数相同.它返回一个适当对齐的存储块,并且可能比所需的稍大.

operator new[]调用该函数void* operator new[](std::size_t).第一个参数可能大于提供给运算符的参数,以便在数组索引需要时提供额外的存储空间.两者的默认实现是简单地调用malloc().

目的operator new[]是支持专门的数组索引(如果可用).它与内存池或其他任何内容无关.在使用此功能的符合实现中,实现将在额外空间中设置专用表,并且编译器将生成用于指令或调用使用这些表的库库支持例程的代码.使用数组并且无法使用new []的C++代码将在这些平台上失败.

我个人并不了解任何此类实现,但它类似于支持某些大型机(CDC,IBM等)所需的功能,这些大型机的架构与我们熟悉和喜爱的Intel或RISC芯片完全不同.

在我看来,接受的答案是不正确的.


为了完整起见,标准(n3936主要在S5.3.4中)包含以下内容.

  1. 分配'数组对象'或'非数组对象'之间的区别
  2. 引用"数组分配开销",暗示可能需要额外的存储,并且可能(某种程度上)用于重复计数或元素大小.

没有引用内存池或任何暗示这可能是一个考虑因素.

  • 然后我认为你误解了标准的那部分是关于什么的......许多现有的实现在返回指针的已知偏移处存储数组中元素数量的计数,以便`delete[]`可以找到那个number 并为适当数量的元素调用析构函数 - 这解释了您提到的标准的所有部分。您的“专用数组索引”和“专用表”听起来像是虚拟地址空间中数组的一些跨内存段碎片,这是一个完全不同的前景,标准没有提及。 (2认同)

Ton*_*roy 5

::operator new[]和〜delete[]便于内存使用调试,是审计分配和解除分配操作的中心点; 然后,您可以确保数组表单既可用于两者,也可用于两者.

如果非常不寻常/原始调整使用,也有很多合理的:

  • 从单独的池中分配数组,可能是因为这对于小型单对象动态分配对象的关键性改进了平均缓存命中率,

  • madvise数组/非数组数据的不同内存访问提示(ala )

所有这些都有点奇怪,超出99.999%的程序员的日常问题,但为什么要阻止它成为可能呢?