If语句与代码块
本节阅读量:
我们将要讨论的第一类控制流语句是条件语句。条件语句会根据某个判断条件,决定是否执行相关语句。
C++支持两种基本类型的条件语句:if语句(之前已经简单介绍过)和switch语句(本章讨论)。
if语句快速回顾
C++中最基本的条件语句类型是if语句。if语句的格式为:
或使用可选的else语句:
1
2
3
4
|
if (条件表达式)
true_对应的语句;
else
false_对应的语句;
|
如果条件的计算结果为true,则执行true对应的语句。如果条件的计算结果为false,并且可选的else语句存在,则执行false对应的语句。
下面是一个简单的程序,它将if语句与可选的else语句一起使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x > 10)
std::cout << x << " is greater than 10\n";
else
std::cout << x << " is not greater than 10\n";
return 0;
}
|
程序运行结果与预期一致:
1
2
|
Enter a number: 15
15 is greater than 10
|
1
2
|
Enter a number: 4
4 is not greater than 10
|
根据if或else的结果执行多条语句
新手程序员通常会这样尝试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <iostream>
namespace constants
{
constexpr int minRideHeightCM { 140 };
}
int main()
{
std::cout << "Enter your height (in cm): ";
int x{};
std::cin >> x;
if (x >= constants::minRideHeightCM)
std::cout << "You are tall enough to ride.\n";
else
std::cout << "You are not tall enough to ride.\n";
std::cout << "Too bad!\n"; // 预期检查失败,才执行这一行
return 0;
}
|
然而,考虑以下程序运行效果:
1
2
3
|
Enter your height (in cm): 180
You are tall enough to ride.
Too bad!
|
该程序不能按预期工作,因为true分支和false分支对应的语句都只能是单条语句。缩进在这里误导了我们——上面的程序实际执行起来就像按如下方式编写一样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include <iostream>
namespace constants
{
constexpr int minRideHeightCM { 140 };
}
int main()
{
std::cout << "Enter your height (in cm): ";
int x{};
std::cin >> x;
if (x >= constants::minRideHeightCM)
std::cout << "You are tall enough to ride.\n";
else
std::cout << "You are not tall enough to ride.\n";
std::cout << "Too bad!\n"; // 预期检查失败,才执行这一行
return 0;
}
|
可以清楚地看到,“Too bad!”这一行总会执行。
然而,通常希望基于某种条件执行多个语句。为此,我们可以使用复合语句(代码块):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <iostream>
namespace constants
{
constexpr int minRideHeightCM { 140 };
}
int main()
{
std::cout << "Enter your height (in cm): ";
int x{};
std::cin >> x;
if (x >= constants::minRideHeightCM)
std::cout << "You are tall enough to ride.\n";
else
{ // 这里使用代码块
std::cout << "You are not tall enough to ride.\n";
std::cout << "Too bad!\n";
}
return 0;
}
|
请记住,代码块会被视为单个语句,因此现在程序可以按预期工作:
1
2
|
Enter your height (in cm): 180
You are tall enough to ride.
|
1
2
3
|
Enter your height (in cm): 130
You are not tall enough to ride.
Too bad!
|
条件结果对应的单条语句是否应该放在代码块中?
对于if或else后面的单个语句是否应显式封装在代码块中,程序员社区中存在争议。
通常有两个理由支持将其放在代码块中。
首先,考虑以下片段:
1
2
|
if (age >= minDrinkingAge)
purchaseBeer();
|
现在,假设有人匆忙修改此程序,想添加另一个功能:
1
2
3
|
if (age >= minDrinkingAge)
purchaseBeer();
driverCar(); // 这一行会永远执行
|
哎呀,未到一定年龄也是不能开车的。这样的修改很容易让某条语句在任何条件下都会执行。
其次,它会使程序更难调试。假设我们有以下片段:
1
2
3
4
|
if (age >= minDrinkingAge)
addBeerToCart();
checkout();
|
假设我们怀疑addBeerToCart()函数有问题,因此将其注释掉:
1
2
3
4
|
if (age >= minDrinkingAge)
// addBeerToCart();
checkout();
|
现在,checkout()变成了满足条件后要执行的语句,这肯定不是我们想要的。
如果总是在if或else语句之后使用代码块,则不会出现这些问题。
不为单条语句添加代码块的主要理由是:代码块会增加垂直间距,让屏幕中一次能看到的代码变少,从而降低可读性,并可能引入其他更严重的错误。
社区整体上更倾向于始终使用代码块,而不是省略代码块。
中间的替代方法是将单个语句放在与if语句相同的一行上:
1
|
if (age >= minDrinkingAge) purchaseBeer();
|
这避免了上面提到的两个缺点,对可读性的影响很小。
最佳实践
考虑将与if或else相关的单条语句放在代码块中(特别是在学习阶段)。
隐式块
如果没有在if else语句中显式使用代码块,编译器会隐式创建代码块。因此:
1
2
3
4
|
if (条件表达式)
true_对应的语句;
else
false_对应的语句;
|
实际上相当于:
1
2
3
4
5
6
7
8
|
if (条件表达式)
{
true_对应的语句;
}
else
{
false_对应的语句;
}
|
大多数时候,这并不重要。然而,新手程序员有时会尝试这样做:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <iostream>
int main()
{
if (true)
int x{ 5 };
else
int x{ 6 };
std::cout << x << '\n';
return 0;
}
|
这段代码无法通过编译,因为编译器会提示标识符x未定义。这是因为上面的示例等效于:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <iostream>
int main()
{
if (true)
{
int x{ 5 };
} // x 这里销毁
else
{
int x{ 6 };
} // x 这里销毁
std::cout << x << '\n'; // x 不在作用域里
return 0;
}
|
这样可以更清楚地看到,变量x具有代码块作用域,并会在代码块末尾被销毁。当执行到std::cout这一行时,x已经不存在。
在下一课中,我们将继续探索if语句。