提问人:gowerc 提问时间:7/7/2023 更新时间:7/7/2023 访问量:158
在 cpp 中,“new int”和“new int[1]”有什么区别?
In cpp what is the difference between `new int` and `new int[1]`?
问:
我目前正在学习 C++,并且正在努力理解以下两行代码之间的区别:
int* a = new int;
int* b = new int[1];
据我了解,这两个语句都返回一个 int 指针,并且只在堆上为 1 int 分配空间。那么,它们之间有什么实际区别,还是只是同义词?
答:
如果你正在学习C++,你不应该关心这里有什么区别吗?
您只应该记住:
- 当我想分配一个简单的变量时,我将使用 和 。
new
delete
- 当我想分配一个数组时,我将使用 和
new[]
delete[]
- 禁止将两者混合使用
在很多例子中,某些编译器成功处理了不正确的代码。甚至在一些例子中,编译器确实将其处理记录为扩展,或者与遗留代码兼容。
但是,如果你现在正在学习 C++,你应该只尝试编写正确的代码,永远不要怀疑是否可以接受轻微的变化。
顺便说一句,正如您在评论中被告知的那样,直接使用显式分配应该只发生在低级代码中,例如对于自定义容器实现。在普通的用户代码中,只需依赖标准容器...
评论
std::vector
;)
new
delete[]
实际上,唯一的区别是您必须使用匹配的删除:
int* a = new int;
int* b = new int[1];
delete a;
delete[] b;
但是,从概念上讲,区别在于创建的对象类型。 创建一个整数,即 . 另一方面,创建一个类型为 的数组。在这两种情况下,您都会从新表达式中得到 a。然而,这只是因为 c 数组有点古怪,它不是指向您刚刚创建的对象的指针,而是指向数组第一个元素的指针。两者的值(数组到第一个元素和指向数组的指针)是相同的,但它们的类型不同,混淆两者可能会导致很多混淆。new int
int
new int[1]
int[1]
int*
b
PS 你不应该在 C++ 中使用 raw。不是单个整数。也不适用于数组。有智能指针和/用于数组。new
std::array
std::vector
正如其他答案中所指出的,规则就是规则,如果你想编写有效的 C++,即使使用未来的编译器,你也必须遵循它们。
但是,在这种情况下,以及大多数其他情况下,规则乍一看似乎是任意的,这是有充分理由的:
表达式 (where )可以是仅在运行时已知的值,它生成指向 s 数组的指针。要解除分配它,请编写 ,其中 是表达式的结果。请注意,您需要指定要分配的数组大小,但不能指定要解除分配的数组大小。
最常见的分配器,用于实现,但是需要知道分配的内存区域的大小才能解除分配。
因此,许多编译器所做的是分配比存储数组所需的内存更多的内存,在分配的内存区域的开头取一小块,并将数组的大小存储在其中。然后,指针将递增到刚好经过存储大小的区域并返回给您。当您释放数组时,程序将递减指针,读取数组大小,并将内存区域的适当大小传递给底层分配器释放函数。new int[N]
N
int
delete[] p
p
new int[N]
new
delete
请注意,这是一个实现细节。不能依赖于在数组之前存储的大小。某些编译器可能会以不同的方式实现数组分配,但这是一种常用方法。C++ 标准仅指定必须始终与 和 匹配。然后,编译器可以自由地做任何它想要或认为最有效的事情。new
delete
new[N]
delete[]
我还应该指出,C++委员会可能已经决定要求你显式地将数组的大小传递给这样:delete[]
delete [N] p;
但他们没有,也许是因为让程序员不必自己存储大小似乎更简单。我个人不同意这个决定,但事情就是这样。
这就是为什么在大多数编译器上,并且会分配不同大小的内存区域,并且结果甚至不会指向底层分配器分配的内存区域的开头。因此,当您尝试解除分配时,您的指针与分配器会非常混乱,因为它会被赋予以前从未分发过的解除分配指针。new int
new int[1]
new int[1]
b
delete b
b
还有强制性的说明:除非你有很好的理由选择后者,否则总是更喜欢和。std::vector<T>
new T[N]
std::make_unique<T>(...)
new T(...)
评论
new int
生成指向 的指针,生成指向 int 数组的指针。您必须通过 和 通过 解除分配。否则,您的程序将具有未定义的行为,并且很可能在实践中崩溃int
new int[1]
a
delete a
b
delete[] b
delete[] b
delete a
delete[] b
delete [] a
delete b
delete
new