【问题标题】:Delete NULL but no compile error删除NULL但没有编译错误
【发布时间】:2009-10-13 03:03:55
【问题描述】:

我很困惑为什么下面的 C++ 代码可以编译。为什么调用删除0的方法没有报错?!

int *arr = NULL;     // or if I use 0, it's the same thing      
delete arr;

我确实尝试过运行它,它根本没有给我任何错误...

【问题讨论】:

  • 代码无法编译 - 您需要指针的类型(例如 void)而不仅仅是限定符;这不是(旧的)C。

标签: c++ null


【解决方案1】:

C++ 语言保证,如果 p 等于 空。

有关更多信息,请查看第 16.8,9 节 here

【讨论】:

  • 不过,问题是为什么代码 compile;不是为什么没有运行时错误。
  • 在 C++ 中删除 NULL 指针是合法的,因此编译器可以接受。
  • 取消引用 null 也合法吗?堆栈溢出怎么办?给我看一个在这些条件下出错的编译器......
  • 就编译器而言,所有这些都是合法的。运行时可能会有不同的看法,当然……
  • 哇,乔希,也许我只是看错了,但你听起来很有防御性之类的。删除 null 很好,它什么都不做。
【解决方案2】:

您可以毫无问题地删除 NULL 指针,并且您可能/可能出现的错误不是在编译时而是在运行时。

int *ptr_A = &a;
ptr_A = NULL;
delete ptr_A;

通常这样做很方便:

...
delete ptr;
ptr = NULL;

【讨论】:

  • 将指针设为 NULL 通常是不好的做法。原因是指针应该封装在类中。 delete 然后出现在析构函数中,之后指针甚至不再存在,或者在赋值中,指针获得一个新值。因此,通常没有将指针设置为 NULL 的方法。一个明显的例外是不再需要的对象的“可选”部分,但请考虑boost::optional<T>
【解决方案3】:

资源释放例程必须接受空指针参数并且什么也不做,这是 C 和 C++ 语言(不仅在它们中)的事实标准。实际上,这是一个相当方便的约定。所以,这里真正的问题是:为什么它让你感到惊讶?是什么让您认为它应该产生错误?此外,是什么让您认为它应该无法编译???

顺便说一句,你的问题,它的陈述方式,似乎没有多大意义,因为你的代码实际上无法编译。假定的指针声明缺少类型,这将使​​任何编译器发出诊断消息。

【讨论】:

  • s/de-facto/de jure/ - 参见 ISO 标准的引用。
【解决方案4】:

NULL 和 0 不是一回事。在 C++ 中,您应该使用 0。

删除空指针在语法上没有任何错误或歧义。事实上,根据定义,这是一个无操作;也就是删除第0个地址的操作相当于什么都不做。

【讨论】:

  • 实际上,在 C++ 中,NULL 被定义为 0。此外,NULL 与 0 是一种风格上的争论,没有明确的答案。
  • 在 C++ 中绝对没有理由偏爱 0 而不是 NULL。尽管出于某种原因,“在 C++ 中使用 0”的建议不时出现。我不知道这个都市传说是从哪里来的,但是,再一次,在 C++ 中使用 NULL 绝对没有错,一般来说,为了可读性,NULL 比 0 更可取。
  • Stroustrup 更喜欢 0 而不是 NULL:research.att.com/~bs/bs_faq2.html#null
  • 在我看来 NULL 是更好的风格,如果只是因为当你在寻找指针问题时你可以搜索它。在使用 0 而不是 NULL 的程序中,搜索 0 将得到 0 的指针和整数使用,并且不相关的额外结果将需要更长的时间来扫描。
  • 答案是否定的:nullptr。由于还没有nullptr,您可以创建此类型并解决问题。也就是说,我觉得 NULL 丑陋。它是全大写(丑陋)、突兀(丑陋)和 ick。
【解决方案5】:

虽然您的示例很简单,但编译器无法(在编译时)知道指针的值。

你也可以在编译时取消对 null 的引用:

// this code compiles
Object* pObject = 0;
pObject->SomeMethod();

编译器不是为了在编译时处理这些类型的错误条件而构建的。

而且大多数(全部?)实现都将“删除 0”作为非操作。这段代码应该可以正常运行:

Object* pObject = new Object();
delete pObject;
pObject = 0;
delete pObject;

虽然我对此不是 100% 确定 :)

【讨论】:

  • 你是对的。不过我遇到了双重删除问题……或者我在想象一些事情?
  • 任何将“删除 NULL”视为空操作以外的任何内容的 C++ 编译器都是有缺陷的编译器。 C++ 语言规定删除 NULL 指针是安全的。 (另一方面,在同一个非 NULL 指针上调用两次 delete 会让你陷入困境)
  • @Jeremy Friesner:我明白你的意思,但从迂腐的角度来看,“删除 NULL”是不正确的。 C++中的'NULL'必须代表一个整数0,'delete'不能应用于整数0。'delete NULL'和'delete 0'一样不正确,即非常:)
  • ...另一方面,'delete (int *) NULL' 是合法的,并且确实必须是空操作。
猜你喜欢
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
相关资源
最近更新 更多