3.1节:逻辑 && 和 || 运算符:短路
&& 的优先级高于 ||,这意味着在评估将一起评估的部分时,会在周围放置括号。
C++ 在 && 和 || 中使用短路评估,以避免执行不必要的操作。
如果 || 的左侧返回 true,则不再需要评估右侧。
#include <iostream>
#include <string>
using namespace std;
bool True(string id) {
cout << "True" << id << endl;
return true;
}
bool False(string id) {
cout << "False" << id << endl;
return false;
}
int main() {
bool result;
// 让我们用 || 和 && 评估 3 个布尔值以说明运算符优先级
// 优先级并不意味着 && 会首先被评估,而是括号会添加在哪里
// 示例 1
result = False("A") || False("B") && False("C");
// 等同于 False("A") || (False("B") && False("C"))
// FalseA
// FalseB
// "短路评估跳过 C"
// A 为 false,因此我们必须评估 || 的右侧,
// B 为 false,我们不需要评估 C 就可以知道结果是 false
result = True("A") || False("B") && False("C");
// 等同于 True("A") || (False("B") && False("C"))
cout << result << " :=====================" << endl;
// TrueA
// "短路评估跳过 B"
// "短路评估跳过 C"
// A 为 true,所以我们不需要评估 || 的右侧就可以知道结果是 true
// 如果 || 的优先级高于 &&,等价的评估将是:
// (True("A") || False("B")) && False("C")
// 这将打印
// TrueA
// "短路评估跳过 B"
// FalseC
// 因为括号的位置不同,被评估的部分也不同,
// 这使得这种情况下的最终结果将是错误的,因为 C 是 false
}
3.2节:一元运算符
一元运算符作用于它们调用的对象,并且具有高优先级。(见备注)
当用作后缀时,操作仅在整个操作被评估后才发生,导致一些有趣的算法:
int a = 1;
++a; // 结果:2
a--; // 结果:1
int minusa = -a; // 结果:-1
a = 4;
int c = a++ / 2; // 等同于:(a==4) 4 / 2 结果:2 ('a' 后置递增)
cout << a << endl; // 打印 5!
int d = ++a / 2; // 等同于:(a+1) == 6 / 2 结果:3
3.3节:算术运算符
C++ 中的算术运算符具有与数学中相同的优先级:
乘法和除法具有左结合性(意味着它们将从左到右进行评估),并且它们的优先级高于加法和减法,后者也具有左结合性。
我们也可以强制表达式的优先级使用括号()。就像你在正常数学中所做的那样。
// 体积的球形壳 = 4 π R^3 - 4 π r^3
double vol = 4.0 * pi * R * R * R / 3.0 - 4.0 * pi * r * r * r / 3.0;
// 加法:
int a = 2 + 4 / 2; // 等同于:2 + (4 / 2) 结果:4
int b = (3 + 3) / 2; // 等同于:(3 + 3) / 2 结果:3
// 乘法:
int c = 3 + 4 / 2 * 6; // 等同于:3 + ((4 / 2) * 6) 结果:15
int d = 3 * (3 + 6) / 9; // 等同于:(3 * (3 + 6)) / 9 结果:3
// 除法和取模:
int g = 3 - 3 % 1; // 等同于:3 % 1 = 0 3 - 0 = 3
int h = 3 - (3 % 1); // 等同于:3 % 1 = 0 3 - 0 = 3
3.4节:逻辑与和或运算符
这些运算符在 C++ 中具有通常的优先级:与(AND)优先于或(OR)。
// 你可以在最多 60 天内使用外国驾照开车
bool can_drive = has_domestic_license || has_foreign_license && num_days <= 60;
这段代码等价于以下形式:
// 你可以在最多 60 天内使用外国驾照开车
bool can_drive = has_domestic_license || (has_foreign_license && num_days <= 60);
添加括号不会改变行为,尽管它确实使编写者的意图更容易理解。