C++ new int [0] - 它会分配内存吗?

228 c++ memory-management standards-compliance new-operator

一个简单的测试应用:

cout << new int[0] << endl;
Run Code Online (Sandbox Code Playgroud)

输出:

0x876c0b8
Run Code Online (Sandbox Code Playgroud)

所以它看起来很有效.标准对此有何看法?"分配"空白内存块总是合法的吗?

Fai*_*ali 229

从5.3.4/7开始

当direct-new-declarator中的表达式的值为零时,将调用分配函数以分配不带元素的数组.

从3.7.3.1/2开始

取消引用作为零大小请求返回的指针的效果是未定义的.

即使[new]请求的空间大小为零,请求也会失败.

这意味着你可以做到,但你不能合法地(在所有平台上以明确定义的方式)取消引用你得到的内存 - 你只能将它传递给数组删除 - 你应该删除它.

这是一个有趣的脚注(即不是标准的规范部分,但包含在说明目的中)附在3.7.3.1/2的句子上

[32.目的是通过调用malloc()或calloc()来实现operator new(),因此规则基本相同.C++与C的不同之处在于要求零请求返回非空指针.

  • @EralpB:相反,即使你的请求为零,这个分配也会发生在Heap上,其中一个请求意味着几个簿记操作,比如在分配器给出的区域之前和之后分配和初始化堆保护,插入freelists或者其他复杂的可怕结构.释放它意味着做落后的簿记. (11认同)
  • @EralpB是的,我猜你每次不平衡`new []`和`delete []`时都会发生内存泄漏 - 无论大小如何.特别是,当你调用`new [i]`时,你需要比你想要分配更多的内存来存储数组的大小(后来在解除分配时由`delete []`使用) (3认同)
  • @ghd:在零大小的情况下,开始指针*是*结束后一位指针,因此您不能递增它。 (3认同)
  • 如果不删除就会出现内存泄漏。是预期的吗?至少我没想到。 (2认同)

小智 21

是的,像这样分配一个零大小的数组是合法的.但是你也必须删除它.

  • 有趣的是,C++不是那么强大,禁止零大小的对象.想想空基类优化:这里,空基类子对象的大小也可以为零.相比之下,C标准努力确保永远不会创建零大小的对象:在定义malloc(0)时,它表示效果是运行带有一些非零参数的malloc.在结构{...; T n []; }; 当没有为数组(FAM)分配空间时,它表示它的行为好像"n"有一个元素.(在这两种情况下,以任何方式使用对象都是UB,如xn [0]) (4认同)

Chr*_*isW 15

标准对此有何看法?"分配"空白内存块总是合法的吗?

每个对象都有一个唯一的标识,即一个唯一的地址,这意味着一个非零长度(如果你要求零字节,实际的内存量将无声增加).

如果您分配了多个这些对象,那么您会发现它们具有不同的地址.


Eva*_*ran 14

是的,分配一个0大小的块是完全合法的new.由于没有有效的数据供您访问,因此您无法对其执行任何有用的操作.int[0] = 5;是非法的.

但是,我相信标准允许malloc(0)返回的东西NULL.

您仍然需要delete []从分配中获得的任何指针.

  • 关于malloc,你是对的 - 它是实现定义的.这通常被视为错误. (5认同)