266

一个简单的测试应用程序:

cout << new int[0] << endl;

输出:

0x876c0b8

所以看起来它有效。标准对此有何评论?“分配”空的内存块总是合法的吗?

4

6 回答 6

249

从 5.3.4/7

当 direct-new-declarator 中表达式的值为零时,调用分配函数来分配一个没有元素的数组。

从 3.7.3.1/2

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

即使 [by new] 请求的空间大小为零,请求也可能失败。

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

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

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

于 2009-07-06T13:46:29.263 回答
24

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

于 2009-07-06T13:45:23.447 回答
15

标准对此有何评论?“分配”空的内存块总是合法的吗?

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

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

于 2009-07-06T13:49:34.877 回答
14

0是的,用 . 分配一个大小的块是完全合法的new。您根本无法对它做任何有用的事情,因为没有可供您访问的有效数据。int[0] = 5;是非法的。

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

您仍然需要delete []从分配中返回的任何指针。

于 2009-07-06T13:47:43.537 回答
2

奇怪的是,即使请求零字节,C++ 也要求 operator new 返回一个合法的指针。(要求这种听起来很奇怪的行为可以简化语言中其他地方的事情。)

我在“第 51 条:编写 new 和 delete 时遵守约定”中发现Effective C++ 第三版是这样说的。

于 2016-05-27T11:51:03.867 回答
2

我向您保证 new int[0] 会花费您额外的空间,因为我已经对其进行了测试。

例如,内存使用情况

int **arr = new int*[1000000000];

明显小于

int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
    arr[i]=new int[0];
}

第二个代码片段的内存使用量减去第一个代码片段的内存使用量就是无数个新 int[0] 使用的内存。

于 2019-12-20T14:48:48.127 回答