没有选择语句的 C++ 条件

laf*_*blu 2 c++ expression if-statement logical-operators

可能是受 Perl 的影响,我喜欢使用下面的语法

condition && do_something();
Run Code Online (Sandbox Code Playgroud)

代替

if ( condition )
{
  do_something();
}
Run Code Online (Sandbox Code Playgroud)

(我知道我可以在没有大括号的情况下将后者放在一行中,但这不是重点。)

我已经进行了几次测试(如下),这些测试有效。但是我在标准中找不到参考,说明它是合法的。它可以隐含在

  • 5.14 逻辑与运算符
  • 5.17 赋值运算符
  • 6.4. 选择声明

但我不完全确定(我检查了 C++ 98,抱歉是老式的,但可能甚至 C 标准就足够了)。

注意:我确实意识到为了工作,最后一个表达式 (do_something) 也必须可以转换为 bool,这对于选择语句来说不是必需的。这当然是一个严重的限制。

所以问题是:

  1. 它是完全合法的吗?
  2. 有理由不使用它吗?
  3. 是否存在可能的副作用(例如导致意外结果的优化)?

抱歉,如果结果是重复的,我找不到任何东西,但可能是因为我没有使用正确的关键字。

#include <cassert>

bool sayYes()
{
  return true;
}

bool sayNo()
{
  return false;
}

int main( int args, char* argv[] )
{
  bool a = true;
  bool b = false;
  int i = 0;

  a && ( i = 1 );
  assert( i == 1 );

  !a && ( i = 0 );
  assert( i == 1 );

  ( a || b ) && ( i = 0 );
  assert( i == 0 );

  sayYes() && ( i = 1 );
  assert( i == 1 );

  ( sayNo() || sayYes() ) && ( i = 0 );
  assert( i == 0 );

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 5

这是完全合法的。来自 [expr.log.and]:

&&保证从左到右的评估:如果第一个操作数是 ,则不评估第二个操作数false

expr() && fun()等价于if (expr()) fun()(假设fun()返回可转换为 的东西bool)。在编写复合条件表达式时,这是一个极其重要的属性。例如,只有在我们知道它是有效的之后才取消引用一个指针:

if (ptr && ptr->foo()) { ... }
Run Code Online (Sandbox Code Playgroud)

也就是说,如果你真正想要的是:

if (expr()) {
    fun();
}
Run Code Online (Sandbox Code Playgroud)

就这么写。无论哪种方式,编译器都会生成相同的代码,但您尝试执行的操作的意图将更加清晰。

  • 自 K&amp;R 以来,在 &amp;&amp; 之后使用未评估的术语一直是惯用的。我发现它很常用,我会继续使用它。它简洁、清晰且适合在一行中,使更多的源代码在编辑器中可见。C++ 允许重载 &amp;&amp; 使事情变得复杂,但我想不出重载 &amp;&amp; 而不以意想不到的方式改变语言工作方式的充分理由。&amp;, OTOH, 可以有效地重载以执行二进制和 int8_t 向量之类的操作,例如处理超长二进制文件。 (2认同)