【问题标题】:Difference between pointer to a new element and new array? [duplicate]指向新元素和新数组的指针之间的区别? [复制]
【发布时间】:2025-12-27 17:20:12
【问题描述】:

在 C++ 中,下面代码中的指针 p 和 q 有什么区别吗?

int* p = new int;
int* q = new int[5];

我知道一个为单个 int 分配新内存,第二个为一个 5 个 int 的数组分配内存,但从根本上说,指向单个 int 的指针和指向 int 数组的指针之间有什么区别吗?

我有这个疑问是因为我读到必须使用 delete[] q 来释放 q 指向的内存,但对于 p 指向的单个 int 只使用 delete p。 如果我使用delete q会怎样?

【问题讨论】:

  • 草率地说,delete 对指针本身并没有多大作用,而是对它指向的东西做太多事情,删除 int 与删除整数数组不同
  • 有些实现会在指针返回之前的地址中跟踪数组的分配大小。这是标准未定义的实现细节。但是,您必须记住使用正确的删除形式。
  • @drescherjm 我想过这样的事情,但我不确定编译器如何找到分配的大小。你能给我指点这方面的更多信息吗?
  • 我没有很好的参考。这个答案更多地谈到了它是如何工作的:*.com/a/1913393/487892
  • @drescherjm 您的答案比当前答案提供的信息更多,所以如果可以,请将其写为答案,以便我将其标记为已接受并关闭问题。

标签: c++


【解决方案1】:

指针本身是完全无法区分的。这就是为什么必须记住匹配new/deletenew[]/delete[]

它们不匹配会触发未定义的行为。

【讨论】:

    【解决方案2】:

    当使用new [] 时,一些c++ 实现会在指针返回之前的地址中跟踪数组分配的大小。这是标准未定义的实现细节。

    以下答案更详细地描述了这种可能的实现:How could pairing new[] with delete possibly lead to memory leak only?

    您必须始终将newdelete 匹配,并将new []delete [] 匹配。混合这些是未定义的行为。

    【讨论】:

    • 这显然是错误的,标准规定指针之间存在多个差异,因此将它们混为一谈会导致未定义的行为。事实是,当程序员忘记差异时,实现没有义务通知他们。
    【解决方案3】:

    在 C++ 中,下面代码中的指针 p 和 q 有什么区别吗?
    指针之间没有可见的区别,但肯定有区别,而且很重要。一个是指向整数的指针,另一个是指向整数的指针,它也是给定大小数组中的第一个元素。

    不幸的是,只有指针,你无法判断。

    如果我使用 delete q 会发生什么?
    可能没有,但可能很多。

    首先,调用delete 而不是delete[] 将在数组的第一个元素上调用析构函数一次,而不是在每个元素上调用。现在,像int 这样的微不足道类型的析构函数没有做任何事情,所以......就目前而言,没有真正的区别。但是,析构函数(或析构函数链)实际执行某些操作的不那么平凡的类型存在巨大差异。

    其次,您正在干扰底层原始内存块的正确释放。这可能(有时确实)导致严重崩溃。由于早期的损坏,它甚至可能导致稍后发生在不相关的、无辜的代码中的崩溃。尝试并调试它。

    或者,您可能会遇到无声的内存泄漏,这取决于实现,有时甚至取决于您在特定情况下的“运气”(例如,是否到达页面边界)。
    因为,好吧,分配和释放数组和分配和释放单个元素并不是一回事。它们(通常)实现略有不同,虽然实现可能能够处理不匹配的new/delete,但不能保证。与正常执行相比,您可能会在调试器中得到不同的行为。

    调用错误形式的delete 意味着调用未定义的行为。这基本上意味着任何事情都可能发生。这包括“无”以及“无法调试的问题”。它还包括编译器恶意优化或仅剥离整个周围函数或假设某个条件始终为真的可能性。这可能会导致非常令人讨厌的惊喜,您会花费数天时间试图弄清楚发生了什么。

    【讨论】: