【问题标题】:Why/When to use (!!p) instead of (p != NULL)为什么/何时使用 (!!p) 而不是 (p != NULL)
【发布时间】:2010-12-09 00:09:05
【问题描述】:

在下面的代码中,使用(!!p)而不是(p != NULL)有什么好处?

AClass *p = getInstanceOfAClass();
if( !!p )
  // do something
else 
  // do something without having valid pointer

【问题讨论】:

  • 我想知道 if (p) 有什么问题。
  • 您应该始终怀疑运算符是否超载。 !p!= 可能有特殊行为。
  • Kobi - 我不记得了,但是重载的运算符是否也适用于对象的 指针?似乎他们不会;如果我是对的,在这种情况下,实际上并没有任何重载运算符问题。 (不管我说得对不对,这是一个很好的观点,而且本身就值得 +1)
  • 他们确实可以Object* operator+(Object const*, Object const*)是一个有效的签名......
  • @Twisol:不,你第一次是对的。不能为非类/非枚举类型重载运算符。非成员重载不会改变任何东西。如果你愿意,你可以声明它,但重载决议永远不会考虑它。在原始示例(指针类型)中,运算符重载是不可能的。

标签: c++ null pointers boolean


【解决方案1】:

给出的例子没有区别。

但是,这适用于所有情况的假设是不正确的。 a = not not ba = b 不同,就整数类型而言。

在 C 中,0 为假。除了0 之外的任何东西都是真的。但是not 01,仅此而已。在 C++ 中,将 true 强制转换为整数 1,这不仅是为了与 C 向后兼容,而且因为 1 不是 0,而 1 是 C bool 类型中用于表示 true 的最常见值,包括Win32中使用的official C bool typeBOOL

虽然对于给出的示例代码,!!p 是不必要的,因为结果被转换为 bool 以评估 if 条件,这并不排除使用 !! 进行转换预期整数值的布尔值。就个人而言,在这个例子中,为了最大限度地提高类型更改和语义清晰的可能性,我会使用NULL != pp != NULL 来明确其含义。

这种技术被称为双键成语,this guy provides some good justifications

【讨论】:

  • 这些理由在这种情况下无效。
  • 实际上在这种情况下 if(p) 和 if(!!p) 相同的。这是因为 'if' 的条件被转换为 bool 并经过测试,这正是 !!最终做。重新链接的答案,在 C++ 中,内核人员可以将他们的值转换为布尔值。
  • “虽然对于给出的示例代码,!!p 显然是不需要的,”也许我应该更清楚地说明这一点。
【解决方案2】:

我认为 GMan 的原始评论应该是公认的答案:

我想知道 if (p) 有什么问题

重点是:没有任何问题,这应该是首选方式。首先,!!p“太聪明了”;这也是完全没有必要的,因此很糟糕(注意:我们在这里讨论的是 if 语句中的指针,因此 Anacrolix 的评论虽然通常有效,但不适用于此处!)。

p != NULL 也是如此。虽然这是可能的,但它不是必需的。这是更多的代码,完全是冗余代码,因此它使代码变得更糟。 Jeff Atwood 说过的最真实的话是“最好的代码就是没有代码”。避免多余的语法。坚持最低限度(这仍然传达了完整的含义;if (p) 完整的)。

最后,if (p) 可以说是用 C++ 编写此代码的最惯用方式。 C++ 向后弯腰为语言中的其他类型(例如数据流)获得相同的行为,但代价是一些非常奇怪的怪癖。该标准的下一个版本甚至引入了新的语法来实现用户定义类型中的这种行为。

对于指针,我们免费获得相同的。所以用它吧。

/编辑:关于清晰度:sharptooth 写道

IMO 与空指针的比较更清晰。

我声称这在客观上是错误的:if (p) 更清晰。在 C++ 中,无论是在这种情况下还是在任何其他情况下,该语句都无法表示其他任何含义。

【讨论】:

  • 我遵循这个。 if( p ) 全部完成,是否简短,是否清楚。 (有些人可能还会称不使用“NULL”的额外好处,因为他们更喜欢“0”)
  • 我更喜欢为布尔类型保留 if (x),为指针类型保留 if (x != nullptr /* or NULL */)。这样,您的指针检查在代码中就会脱颖而出,并且易于搜索。
  • “这个语句不可能有其他含义” - if (p != NULL) 也不可能有任何含义,但 p 不等于 NULL,无论 NULL 可能是什么是。
  • @Ed:是的,但是p != NULL 提供了多余的信息。与if (p)相比,优势在哪里?
【解决方案3】:

千万不要使用双重否定。一个简单的论点是,由于 C++ 是有限的英语子集,并且英语没有双重否定,因此说英语的人将很难解析正在发生的事情。

【讨论】:

  • 除非您还上过拉丁语课程,否则双重否定(取决于上下文)不会被取消,但否定的含义会被放大。
  • 除了! (C++ 是有限的英语子集)。
  • @MP24?愿意举个例子吗?我只知道相反的情况(例如“non ignoro”),双重否定用于放大肯定断言(在这种情况下:“我知道非常好”而不是“我不知道”)。至于英语:“ain't got no money”是完全有效的白话(Steven Pinker 甚至用它作为例子),其中(在这个意义上)双重否定被 drop 支持简单否定:“否”取代“任何”。在(标准)法语中也是如此,“je n'ai pas d'argent”字面意思是“我没有钱”,但意思恰恰相反。 </off topic>
【解决方案4】:

它们是相同的,但我建议使用

NULL != p

它更具可读性。

【讨论】:

  • 它的可读性值得商榷。就我个人而言,我觉得它的可读性较少,仅仅是因为它不自然地阅读。我通常说“如果 p 不是 NULL”而不是“如果 NULL 不是 p”。
  • 是的,但它确实可以防止人们错过错误的“p = NULL”,因为编译器会拾取“NULL = p”。
  • @ChrisBD:我认识的任何编译器都会选择“p = NULL”。除非你禁用了警告,否则你不应该这样做。
  • 我同意它比双重否定更具可读性,但是我反对您声称它比!!pp != NULL 更具可读性的说法。忽略警告的开发人员应该花费数小时寻找“条件赋值”错误——除了学习不要忽略警告之外别无其他原因。与 DevSolar 一样,我也强烈希望为草率的开发实践引入变通办法。
  • OP: '使用 (!!p) 而不是 (p != NULL) 有什么好处' Catalin: '它们是一样的,但我建议使用 NULL != p 更多可读。也许只有我一个人,但我认为这是“NULL != p 比他们俩都更具可读性。”
【解决方案5】:

几乎是一样的,虽然我认为!!p 的风格很糟糕,并且通常表示编码员试图变得聪明。

【讨论】:

  • 如果你花了一个小时来编写聪明的代码,那么几周后你就需要两个人来理解它。
  • 我完全同意。它应该读作“试图变得聪明,却失败了”
【解决方案6】:

据我所知,这只是将其转换为布尔值的一种更短的方法。它适用于!但是,两次,而p != NULL 进行了一次比较。所以我想好处只是代码更短,尽管如果你不知道!!p 应该是什么意思会更神秘。

【讨论】:

    【解决方案7】:

    这是风格问题,实际上它们是等价的。请参阅this very similar question 进行讨论。

    IMO 与空指针的比较更清晰。

    【讨论】:

      猜你喜欢
      • 2012-06-27
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多