如何用 C++ 写出优雅的条件表达式

可能有人没有注意过,大部分程序语言都是区分 语句(statement) 和 表达式(expression)的,二者的区别是,如果我们写了一条语句,我们是想要得到它的副作用(effect),如果我们写了一条表达式,我们是想要得到它的值(value)。比如:
int a = b + c; 这是一条语句,我们想要的是“赋值”给a的副作用。其中 b + c 是表达式,我们想要的是 b + c 的值。对表达式支持良好(更时髦一些的说法可能应该是支持表达式是一等公民?)的语言可以写出非常好看的代码,比如在 Rust 里你可以写出类似这样的代码:

let remark = match(score) {
    90..=100 => "A",
    80..90 => "B",
    60..80 => "C",
    _ => "D"
};

match 是 Rust 中模式匹配,暂且我们就把它当做就是 C++ 中的 switch 吧。C++ 不支持 if 或者 switch 表达式,所以不出意外,同样的逻辑,一般我们会这样写:

std::string remark = "";
if (90 <= score && score <= 100) remark = "A"; 
else if (80 <= score && score < 90) remark = "B"; 
else if (60 <= score && score < 80) remark = "C";
else remark = "D";

你也许会说,这有什么问题,不过是多写了几行 remark = ...。确实,但写法啰嗦只是缺点之一。如果我们想要 remark 不是变量,而是常量呢?我们没法直接声明 const std::string remark = "" 然后再给它赋值了。而 Rust 版本的可以做到,这就是表达式的优雅之处。

不过庆幸(还是说不幸?很多人说 C++ 越来越复杂)我们有现代的 C++,也可以写出优雅的代码。通过使用即时调用的 lambda 函数,我们也能模拟出一个复杂的 if 表达式,忘掉三目运算符吧:

#include <iostream>

int main(int argc, char *argv[]) {
  int score = 90;
  const std::string remark = [&]() { // 我们可以声明为 const 了。
      if (90 <= score && score <= 100) return "A"; 
      else if (80 <= score && score < 90) return "B"; 
      else if (60 <= score && score < 80) return "C";
      else return "D";
  }(); // 注意最末尾的 (),我们立即执行了这个 lambda。

  std::cout << "remark: " <<  remark << std::endl;

  return 0;
}

“即用即抛” 的 lambda 有很多类似这样的妙用,让 C++ 仿佛支持了 if/switch 表达式。或许有人会说,这么写怎么有点像 JavaScript…

总结一下,对于简短的变量初始化,可以这样用,尤其是如果想要声明成 const 常量的话。因为本来就算用 if statement 我们也不一定会把它封成一个函数,对可读性并没有太大影响。其实我觉得是提高了可读性,因为没有了多次的赋值操作。当然,我们也必须要杜绝那种又臭又长的 lambda,不能把 lambda 当成函数定义来用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值