众所周知,C ++标准定义了两种形式的全局分配函数:
void* operator new(size_t);
void* operator new[](size_t);
此外,C ++标准草案(18.6.1.2 n3797)说:
227)这不是运营商的直接责任 new或operator delete注意重复 计数或数组的元素大小。执行这些操作 数组new和delete表达式中的其他位置。阵列新 但是,可以将size参数增加到operator 新的,以获得存储补充信息的空间。
令我困惑的是:
如果我们从标准中删除void* operator new[](size_t);
该怎么办,而只是使用void* operator new(size_t)
呢?什么是定义冗余全局分配函数的基本原理?
答案 0 :(得分:12)
我认为::operator new[]
对于相当专业的系统可能是有用的,其中“大但很少”的数组可能由不同的分配器分配,而不是“小而多”的对象。然而,它目前是一种遗物。
operator new
可以合理地期望在返回的确切地址处构造对象,但operator new[]
不能。分配块的第一个字节可能用于大小“cookie”,数组可能被稀疏地初始化,等等。区别对于成员operator new
更有意义,它可能专门用于其特定的类。
在任何情况下,::operator new[]
都不是非常重要,因为std::vector
(通过std::allocator
),这是目前最流行的获取动态数组的方式,忽略它。
在现代C ++中,自定义分配器通常是比自定义operator new
更好的选择。实际上,应该完全避免使用new
表达式来支持容器(或智能指针等)类,这样可以提供更多的异常安全性。
答案 1 :(得分: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中)包含以下内容。
没有引用内存池或任何提示,这可能是一个考虑因素。
答案 2 :(得分:5)
::operator new[]
和〜delete[]
有助于内存使用调试,是审计分配和解除分配操作的中心点;然后,您可以确保数组表单既可用于两者,也可用于两者。
如果非常不寻常/原始调整使用,也有很多合理的东西:
从单独的池中分配数组,可能是因为这对于小型单对象动态分配对象的关键性改进了平均缓存命中率,
数组/非数组数据的不同内存访问提示(ala madvise
)
所有这些都有点奇怪,超出99.999%的程序员的日常问题,但为什么要阻止它成为可能呢?
答案 3 :(得分:2)
我确定有适当的用例需要单独的new[]
和new
,但我还没有遇到过这种情况,这种分离和没别的。
但是,我看到它是这样的:因为用户调用了不同版本的运算符new
,所以C ++标准会犯下肆无忌惮的故意丢失信息如果他们' d只定义了一个operator new
并且同时向new
和new[]
转发。这里有(字面意思)一点信息,可能对某人有用,我不认为委员会中的人可能会把它扔出去良心!
此外,必须实施额外的new[]
对我们其他人来说是一个非常非常小的不便,如果有的话,所以保留一点信息的权衡胜过必须实现一个简单的在我们程序的一小部分中起作用。
答案 4 :(得分:-1)
C ++编程语言:特别版 p 423说
_ operator new()
和operator delete()
函数允许用户接管单个对象的分配和释放; operator new[]()
和operator delete[]()
为数组的分配和释放提供完全相同的角色。
感谢Tony D纠正我对这种细微差别的误解。
哇,我不常常被C ++中的某些东西所吸引,我非常肯定 - 我一定是在Objective-C上花了太多时间!
原始错误答案
这很简单 - 经典C数组的每个元素上的新[]形式invokes the constructor。
所以它首先为所有对象分配空间,然后迭代调用每个槽的构造函数。