在许多语言中,作业在条件下是合法的。我一直不明白这背后的原因。你为什么要写:
if (var1 = var2) {
...
}
代替:
var1 = var2;
if (var1) {
...
}
在许多语言中,作业在条件下是合法的。我一直不明白这背后的原因。你为什么要写:
if (var1 = var2) {
...
}
代替:
var1 = var2;
if (var1) {
...
}
循环比 if 语句更有用。
while( var = GetNext() )
{
...do something with var
}
否则必须写
var = GetNext();
while( var )
{
...do something
var = GetNext();
}
我发现它在通常涉及错误检测等的操作链中最有用。
if ((rc = first_check(arg1, arg2)) != 0)
{
report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
report error based on new rc
}
else
{
do what you really wanted to do
}
替代方案(不使用条件中的分配)是:
rc = first_check(arg1, arg2);
if (rc != 0)
{
report error based on rc
}
else
{
rc = second_check(arg2, arg3);
if (rc != 0)
{
report error based on new rc
}
else
{
rc = third_check(arg3, arg4);
if (rc != 0)
{
report error based on new rc
}
else
{
do what you really wanted to do
}
}
}
通过延长错误检查,替代方案可以在页面的 RHS 之外运行,而条件分配版本则不会这样做。
错误检查也可以是“动作”——、、、first_action()
——当然second_action()
,third_action()
而不仅仅是检查。也就是说,可以在该功能管理的过程中检查它们的步骤。(大多数情况下,在我使用的代码中,函数与前置条件检查,或函数工作所需的内存分配,或类似的行一致)。
如果您正在调用一个函数,它会更有用:
if (n = foo())
{
/* foo returned a non-zero value, do something with the return value */
} else {
/* foo returned zero, do something else */
}
当然,你可以把 n = foo(); 在单独的语句 then if (n),但我认为上面是一个相当易读的习语。
如果您调用的函数返回要处理的数据或指示错误(或您已完成)的标志,这将很有用。
就像是:
while ((c = getchar()) != EOF) {
// process the character
}
// end of file reached...
就个人而言,这是一个我不太喜欢的成语,但有时替代方案更丑陋。
如果您无意中尝试使用赋值作为真值,GCC 可以帮助您检测(使用 -Wall),以防它建议您编写
if ((n = foo())) {
...
}
即使用额外的括号表示这确实是您想要的。
当您编写while
循环而不是if
语句时,该成语更有用。对于if
声明,您可以按照您的描述将其分解。但是如果没有这个结构,你要么必须重复自己:
c = getchar();
while (c != EOF) {
// ...
c = getchar();
}
或使用循环半结构:
while (true) {
c = getchar();
if (c == EOF) break;
// ...
}
我通常更喜欢循环半形式。
例如,在 PHP 中,它对于遍历 SQL 数据库结果很有用:
while ($row = mysql_fetch_assoc($result)) {
// Display row
}
这看起来比:
$row = mysql_fetch_assoc($result);
while ($row) {
// Display row
$row = mysql_fetch_assoc($result);
}
另一个优点是在使用 gdb 期间。在下面的代码中,如果我们单步执行,则不知道错误代码。
while (checkstatus() != -1) {
// process
}
相当
while (true) {
int error = checkstatus();
if (error != -1)
// process
else
//fail
}
现在,在单步中,我们可以知道 checkstatus() 的返回错误代码是什么。
boost::optional
我发现它对于返回可选项(或std::optional
在 C++17 中)的函数非常有用:
std::optional<int> maybe_int(); // function maybe returns an int
if (auto i = maybe_int()) {
use_int(*i);
}
这减少了我的变量的范围,使代码更紧凑并且不妨碍可读性(我发现)。
与指针相同:
int* ptr_int();
if (int* i = ptr_int()) {
use_int(*i);
}
我今天在用 Arduino(C 语言)编程时使用它。
我有一个发射器和一个接收器。发送器想要发送数据,直到它被接收到。我想在过程完成后设置一个标志。
while (!(newtork_joined = transmitter.send(data))) {
Serial.println("Not Joined");
}
这里:
传输不成功时,不设置标志,while循环为真,一直执行
成功时,设置标志,while循环为假,我们退出
不漂亮吗?
原因是:
性能改进(有时)
更少的代码(总是)
举个例子:有一个方法someMethod()
,在一个if
条件下要检查方法的返回值是否为null
. 如果没有,您将再次使用返回值。
If(null != someMethod()){
String s = someMethod();
......
//Use s
}
由于您两次调用相同的方法,因此会影响性能。而是使用:
String s;
If(null != (s = someMethod())) {
......
//Use s
}