为什么要使用短路代码?

时间:2009-11-16 20:24:32

标签: coding-style short-circuiting code-structure

相关问题Benefits of using short-circuit evaluationWhy would a language NOT use Short-circuit evaluation?Can someone explain this line of code please? (Logic & Assignment operators)

有一些关于使用短路代码的语言的好处的问题,但我想知道程序员有什么好处?只是它可以让代码更简洁吗?还是有性能原因?

我不是在询问需要评估两个实体的情况,例如:

if($user->auth() AND $model->valid()){
  $model->save();
}

对我而言,原因很清楚 - 既然两者都必须如此,那么如果用户无法保存数据,您可以跳过更昂贵的模型验证。

这对我来说也有明显的目的:

if(is_string($userid) AND strlen($userid) > 10){
  //do something
};

因为使用非字符串值调用strlen()是不明智的。

我想知道的是当它不影响任何其他陈述时使用短路代码。例如,从Zend Application默认索引页面:

defined('APPLICATION_PATH')
 || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

这可能是:

if(!defined('APPLICATION_PATH')){
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
}

或者甚至作为一个声明:

if(!defined('APPLICATION_PATH'))
  define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

那么为什么要使用短路代码呢?仅仅因为使用逻辑运算符代替控制结构的“酷”因素?要合并嵌套的if语句?因为它更快?

9 个答案:

答案 0 :(得分:4)

用它来混淆人们!

答案 1 :(得分:4)

我不知道PHP,我从未见过在C系列语言中在if或while条件之外使用的短路,但在Perl中,它是非常惯用的说法:

open my $filehandle, '<', 'filename' or die "Couldn't open file: $!";

在一个语句中使用all的一个优点是变量声明。否则你不得不说:

my $filehandle;
unless (open $filehandle, '<', 'filename') {
    die "Couldn't open file: $!";
}

很难说第二个在这种情况下更清洁。并且它仍然是一种没有unless

的语言

答案 2 :(得分:4)

对于程序员来说,与另一种更详细的语法相比,语法更简洁的好处可能是:

  • 更少打字,因此编码效率更高
  • 阅读量少,因此可维护性更好。

现在我只是在讨论那些不那么详细的语法在任何方面都不是棘手或聪明的,只是用同样的公认方式,而是用更少的字符。

通常当你看到一种语言中的特定结构你希望你使用的语言可能有,但之前甚至都没有意识到。我头顶的一些例子:

  • Java中的匿名内部类,而不是传递指向函数的指针(更多行代码)。
  • 在Ruby中,|| =运算符,用于计算表达式并在其计算结果为false或为null时赋值给它。当然,您可以通过3行代码实现相同的功能,但为什么呢?
  • 以及更多...

答案 3 :(得分:2)

我认为你的例子是冷静因素。没有理由编写这样的代码。

编辑:出于惯用原因我没有问题。如果使用某种语言的其他人都使用短路评估来制作每个人都能理解的类似语句的实体,那么您也应该这样做。但是,我的经验是,那种代码很少用C语言编写;正确的形式只是使用“if”语句正常,它将条件(可能没有副作用)与条件控件(可能有很多副作用)的函数调用分开。

答案 4 :(得分:2)

短路运算符在两个尚未提及的重要情况下非常有用:

案例1 。假设你有一个指针,可能是NULL,也可能不是NULL,你想检查它是不是0,而它指向的东西不是if (a != NULL) { if (*a != 0) { ⋮ } } 。但是,如果指针为NULL,则必须才能取消引用指针。没有短路操作员,您必须这样做:

if (a != NULL && *a != 0) {
  ⋮
}

但是,短路运算符允许您更紧凑地编写它:

*a

如果aNULL,则会my $file = $user_filename || find_file_in_user_path() || find_file_in_system_path() || $default_filename;

}。

案例2 。如果要将变量设置为从一系列函数之一返回的非假值,则可以执行以下操作:

$file

这会将$user_filename的值设置为find_file_in_user_path()(如果存在),或{{1}}的结果(如果是),或者......等等。在Perl中可能比C更常见,但我在C中看到过它。

还有其他用途,包括您在上面引用的相当人为的例子。但它们是一个有用的工具,也是我在用较不复杂的语言编程时遗漏的工具。

答案 5 :(得分:1)

与丹所说的相关,我认为这完全取决于每种编程语言的惯例。我看不出有任何区别,所以在每种编程语言中做任何惯用语。有一点可以让人想到的是,如果你不得不进行一系列检查,那么短路风格会比风格更清晰。

答案 6 :(得分:0)

如果您有一个昂贵的调用(性能明智)函数,如果另一个条件为真(或错误),则在右侧返回一个您只想调用的布尔值,该怎么办?在这种情况下,短路可以节省很多CPU周期。它确实使代码更简洁,因为嵌套的if语句更少。因此,出于您在问题末尾列出的所有原因。

答案 7 :(得分:0)

事实上,实际上是表现。编译器使用短路来消除死代码,从而节省文件大小和执行速度。在运行时,短路不会执行逻辑表达式中的剩余子句,如果它们的结果不影响答案,则加快公式的评估。我正在努力记住一个例子。 e.g

a AND b AND c

此公式中有两个术语从左到右进行评估。

如果AND b的计算结果为FALSE,那么下一个表达式AND c可以是FALSE和TRUE,也可以是FALSE和FALSE。无论c的值是什么,两者都评估为FALSE。因此编译器不会在编译格式中包含AND c,因此会使代码短路。

要回答这个问题,有些特殊情况是编译器无法确定逻辑表达式是否具有常量输出,因此不会使代码短路。

答案 8 :(得分:0)

如果你有像

这样的陈述,可以这样想
if( A AND B )
如果A返回FALSE,你很可能只想在罕见的特殊情况下评估B.因此,不使用简短的评估会令人困惑。

短路评估还可以通过阻止另一个括号内的缩进和括号添加的趋势使您的代码更具可读性。