8

(我不是很需要这个答案,我只是好奇。)

是否可以使用条件运算符将每个 if-else 构造替换为等效的条件表达式?:

4

8 回答 8

11

是否可以使用条件运算符将每个 if-else 构造替换为等效的条件表达式?

不,你是倒过来问的。 if/else 的“主体”包含语句,不可能将每个语句都变成一个表达式,例如 try、while、break 语句以及声明。然而,许多“陈述”实际上是变相的表达:

++i;
blah = 42;
some_method(a,b,c);

所有这些都是由一个表达式(分别为增量、赋值、函数调用)组成的语句,并且可以转换为条件内的表达式。

所以,让我们把问题反过来,因为听起来你真的很想知道 if/else 语句与三元条件表达式的等效性:每个条件表达式都可以被等效的 if/else 语句替换吗? 几乎所有,是的。一个常见的例子是 return 语句:

return cond ? t : f;
// becomes:
if (cond) return t;
else return f;

但也有其他表达:

n = (cond ? t : f);
// becomes:
if (cond) n = t;
else n = f;

这开始指向条件表达式不能轻易替换的地方:初始化。由于您只能初始化一个对象一次,因此您必须将使用条件的初始化分解为使用显式临时变量:

T obj (cond ? t : f);
// becomes:
SomeType temp;
if (cond) temp = t;
else temp = f;
T obj (temp);

请注意,这更加乏味/繁琐,并且如果 SomeType 无法默认构造和分配,则需要依赖于类型的东西。

于 2009-11-30T08:02:41.887 回答
4

从表面上看,没有。条件运算符是一个表达式(即它有一个值),而 if/else 是一个语句(因此没有值)。它们满足语言语法中的不同“需求”。

但是,由于您可以忽略表达式值,并且由于可以通过添加分号将任何表达式转换为语句,因此您基本上可以使用条件表达式和两个辅助函数来模拟 if/else:

// Original code:
if (condition) {
  // block 1
}
else {
  // block 2
}

// conditional expression replacement:

bool if_block() {
  // block 1
  return true;
}

bool else_block() {
  // block 2
  return true;
}

// Here's the conditional expression.  bool value discarded:
condition ? if_block() : else_block();

但是,话虽如此,我不确定这只是出于好奇……

于 2009-11-30T07:49:37.310 回答
2

不,当然不。由于已经提到的原因,还有更多!

#include <cstdlib>
#include <iostream>

int main()
{
    if(int i = std::rand() % 2)
    {
        std::cout << i << " is odd" << std::endl;
    }
    else
    {
        std::cout << i << " is even" << std::endl;
    }
}

查看声明的位置。这不是一种经常使用的技术,但它可以用于像 COM 这样的情况,其中每个调用都返回 HRESULT,它(几乎总是)成功时为零(S_OK),失败时非零,所以你可以写如下内容:

if(HRESULT hr = myInterface->myMethod())
{
    _com_raise_error(hr);
}

三元运算符不能做任何类似的事情。

于 2009-11-30T12:23:34.723 回答
1

条件运算符希望两个项目都?位于右值之后(因为条件运算符的结果本身就是一个右值) - 所以虽然我并不完全是 C/C++ 标准的专家,但我的直觉是以下将被禁止(或失败,极差的编码风格......):

(condition) ? return x : return y;

而 if-else 版本将非常标准:

if(condition) return x;
else return y;

现在,就是说,你能用任何程序编写一个功能相似但不使用 if-else 的程序吗?当然,你可能可以。但这并不意味着这将是一个好主意。;)

于 2009-11-30T07:42:31.587 回答
1

使用条件运算符会产生一个表达式,并且条件运算符的两个潜在结果必须是“兼容的”(可转换为相同的类型)。

一个if-else构造甚至不需要从两个分支“返回”任何类型,更不用说相同的类型了。

于 2009-11-30T07:43:05.713 回答
1
if( cond )
    break;
else
    a=b;

不能总是由?:操作员代替。您可以经常(如果不是总是)重新考虑您的整个代码以提供此替代品,但通常您不能将任何控制执行的内容放入?:. break, return, 循环throw, 等等。

于 2009-11-30T08:00:48.177 回答
1

原则上,是的:

if (A) B; else C

变成

try {
  A ? throw TrueResult() : throw FalseResult();
  // or: throw A ? TrueResult() : FalseResult();
} catch (TrueResult) {
  B;
} catch (FalseResult) {
  C;
}

与使用过程(更自然)相比,这允许break,continuereturn。它需要评估A不以TrueResult/结尾,FalseResult但如果您仅使用这些异常来模拟if,则不会有问题。

于 2009-11-30T09:27:20.480 回答
0

GCC 有statement expression,使用它你可以将语句重写if为等价的?:表达式:

if (<expression>)
  <statement1>
else
  <statement2>

编辑:void演员有两个目的。中的子表达式?:必须具有相同的类型,并且没有强制转换void编译器可以打印warning: statement with no effect.

(<expression>)? (void)({<statement1>}) : (void)({<statement2>});
于 2009-11-30T09:00:15.963 回答