第5章 分支语句和逻辑运算符

分支语句

if 语句的高级用法

复合条件与逻辑组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 使用逻辑运算符组合条件
if (age >= 18 && age <= 65) {
std::cout << "You are eligible to work" << std::endl;
}

// 使用括号提高可读性和优先级控制
if ((temperature > 0 && temperature < 100) || isWater) {
std::cout << "Water is in liquid state" << std::endl;
}

// 复杂条件的结构化表达
if ( (userRole == UserRole::Admin || userRole == UserRole::Moderator)
&& (action == Action::Edit || action == Action::Delete)
&& !isRestricted(resourceId)) {
// 授权执行操作
performAction(resourceId, action);
}

嵌套 if 语句的优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 传统嵌套if语句
if (score >= 60) {
if (score >= 90) {
std::cout << "Grade: A" << std::endl;
} else if (score >= 80) {
std::cout << "Grade: B" << std::endl;
} else if (score >= 70) {
std::cout << "Grade: C" << std::endl;
} else {
std::cout << "Grade: D" << std::endl;
}
} else {
std::cout << "Grade: F" << std::endl;
}

// 优化:使用早期返回减少嵌套
std::string getGrade(int score) {
if (score < 60) return "F";
if (score < 70) return "D";
if (score < 80) return "C";
if (score < 90) return "B";
return "A";
}

// 优化:使用查找表(适用于离散值)
std::string getGradeUsingLookup(int score) {
static const std::vector<std::pair<int, std::string>> gradeTable = {
{90, "A"},
{80, "B"},
{70, "C"},
{60, "D"},
{0, "F"}
};

for (const auto& [minScore, grade] : gradeTable) {
if (score >= minScore) {
return grade;
}
}
return "F";
}

if 语句的初始化语句(C++17+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 在if语句中初始化变量
if (auto user = getUser(userId); user.isValid()) {
// 使用user对象
processUser(user);
} else {
// 处理无效用户
handleInvalidUser(userId);
}

// 结合智能指针
if (auto resource = std::make_unique<Resource>(); resource->initialize()) {
// 使用初始化后的资源
resource->process();
} // resource自动释放

// 结合RAII和文件操作
if (std::ifstream file("data.txt"); file.is_open()) {
// 读取文件
std::string line;
while (std::getline(file, line)) {
processLine(line);
}
} // file自动关闭

if constexpr(C++17+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 编译时条件判断
template <typename T>
void processValue(T value) {
if constexpr (std::is_integral_v<T>) {
// 处理整数类型
std::cout << "Integral value: " << value << std::endl;
} else if constexpr (std::is_floating_point_v<T>) {
// 处理浮点类型
std::cout << "Floating point value: " << value << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
// 处理字符串类型
std::cout << "String value: " << value << std::endl;
} else {
// 处理其他类型
std::cout << "Other type" << std::endl;
}
}

// 编译时接口检测
template <typename T>
auto getLength(const T& value) {
if constexpr (requires { value.size(); }) {
// 类型具有size()方法
return value.size();
} else if constexpr (requires { std::size(value); }) {
// 类型支持std::size()
return std::size(value);
} else {
// 不支持长度获取
return -1;
}
}

if 语句的汇编级实现与优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 简单if语句的汇编分析
void simpleIf(int x) {
if (x > 0) {
// 条件为真的分支
x = x * 2;
} else {
// 条件为假的分支
x = x * 3;
}
}

// 对应的x86-64汇编(GCC 11.2,-O2优化)
// simpleIf(int):
// test edi, edi
// jle .L2
// lea eax, [0+rdi*2]
// ret
// .L2:
// lea eax, [0+rdi*3]
// ret

分支预测优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 分支预测友好的代码:将常见情况放在前面
void processData(bool isCommonCase) {
if (isCommonCase) {
// 处理常见情况(分支预测容易成功)
handleCommonCase();
} else {
// 处理罕见情况(分支预测可能失败)
handleRareCase();
}
}

// 避免不可预测的分支
// 不好的做法:随机条件导致分支预测失败
void processRandomData() {
if (rand() % 2 == 0) {
// 随机分支
} else {
// 随机分支
}
}

// 好的做法:使用条件移动指令代替分支
int max(int a, int b) {
// 现代编译器会生成条件移动指令,无分支
return a > b ? a : b;
}

// 对应的x86-64汇编(使用条件移动)
// max(int, int):
// cmp edi, esi
// mov eax, esi
// cmovg eax, edi
// ret

switch 语句的高级用法

枚举类型与 switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 枚举类型与switch
enum class Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
};

void printDayActivity(Day day) {
switch (day) {
case Day::MONDAY:
case Day::TUESDAY:
case Day::WEDNESDAY:
case Day::THURSDAY:
case Day::FRIDAY:
std::cout << "Go to work" << std::endl;
break;
case Day::SATURDAY:
case Day::SUNDAY:
std::cout << "Weekend - relax" << std::endl;
break;
// 对于强类型枚举,编译器会检查是否覆盖所有枚举值
// 不需要default分支(如果所有枚举值都已覆盖)
}
}

// 结合std::to_underlying(C++23+)
enum class Status : int {
OK = 200,
NOT_FOUND = 404,
SERVER_ERROR = 500
};

void handleStatus(Status status) {
switch (status) {
case Status::OK:
std::cout << "Status: OK (" << std::to_underlying(status) << ")" << std::endl;
break;
case Status::NOT_FOUND:
std::cout << "Status: Not Found (" << std::to_underlying(status) << ")" << std::endl;
break;
case Status::SERVER_ERROR:
std::cout << "Status: Server Error (" << std::to_underlying(status) << ")" << std::endl;
break;
}
}

switch 语句中的变量定义与作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// switch语句中的变量定义
switch (choice) {
case 1: {
int value = 100;
std::cout << "Choice 1: " << value << std::endl;
break;
}
case 2: {
int value = 200; // 不同作用域,可以重名
std::cout << "Choice 2: " << value << std::endl;
break;
}
default:
std::cout << "Invalid choice" << std::endl;
break;
}

// 共享变量的作用域
switch (choice) {
int sharedValue = 0; // 在所有case分支中可见
case 1:
sharedValue = 100;
std::cout << "Choice 1: " << sharedValue << std::endl;
break;
case 2:
sharedValue = 200;
std::cout << "Choice 2: " << sharedValue << std::endl;
break;
default:
sharedValue = -1;
std::cout << "Invalid choice: " << sharedValue << std::endl;
break;
}

switch 语句的初始化语句(C++17+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 在switch语句中初始化变量
switch (auto user = getUser(); user.getType()) {
case UserType::Guest:
std::cout << "Guest user" << std::endl;
break;
case UserType::Member:
std::cout << "Member user" << std::endl;
break;
case UserType::Admin:
std::cout << "Admin user" << std::endl;
break;
default:
std::cout << "Unknown user type" << std::endl;
break;
}

// 结合智能指针
switch (auto resource = std::make_shared<Resource>(); resource->getStatus()) {
case ResourceStatus::Available:
resource->acquire();
break;
case ResourceStatus::Busy:
std::cout << "Resource is busy" << std::endl;
break;
case ResourceStatus::Error:
std::cout << "Resource error" << std::endl;
break;
}
// resource自动释放

switch 语句与模式匹配(C++26 预览)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 模式匹配示例(C++26)
struct Point {
int x, y;
};

void processPoint(const Point& p) {
switch (p) {
case {0, 0}:
std::cout << "Origin" << std::endl;
break;
case {x, 0}:
std::cout << "On x-axis: " << x << std::endl;
break;
case {0, y}:
std::cout << "On y-axis: " << y << std::endl;
break;
case {x, y}:
std::cout << "Point: (" << x << ", " << y << ")" << std::endl;
break;
}
}

// 模式匹配与类层次结构
class Base { virtual ~Base() {} };
class Derived1 : public Base { int value; };
class Derived2 : public Base { std::string name; };

void processBase(Base* ptr) {
switch (ptr) {
case nullptr:
std::cout << "Null pointer" << std::endl;
break;
case Derived1* d1:
std::cout << "Derived1 with value: " << d1->value << std::endl;
break;
case Derived2* d2:
std::cout << "Derived2 with name: " << d2->name << std::endl;
break;
case Base* b:
std::cout << "Base class" << std::endl;
break;
}
}

switch 语句的性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 优化case顺序:将最常见的case放在前面
void processCommand(int command) {
switch (command) {
case COMMAND_EXECUTE: // 最常见的命令
executeCommand();
break;
case COMMAND_STATUS: // 次常见的命令
getStatus();
break;
case COMMAND_HELP: // 较少见的命令
showHelp();
break;
// 其他命令...
default:
handleUnknownCommand(command);
break;
}
}

// 对于连续的整数值,编译器会生成跳转表
// 对于稀疏的整数值,编译器会生成二分查找

// 避免复杂的switch体
// 不好的做法:在switch体中包含复杂逻辑
switch (option) {
case 1:
// 100行复杂代码
break;
case 2:
// 另100行复杂代码
break;
// ...
}

// 好的做法:将复杂逻辑提取为函数
switch (option) {
case 1:
handleOption1();
break;
case 2:
handleOption2();
break;
// ...
}

switch 语句的底层实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// switch语句的汇编实现分析
void switchExample(int value) {
switch (value) {
case 0:
// 处理0
break;
case 1:
// 处理1
break;
case 2:
// 处理2
break;
default:
// 处理默认情况
break;
}
}

// 对应的x86-64汇编(使用跳转表)
// switchExample(int):
// cmp edi, 2
// ja .L8
// jmp [QWORD PTR .L4[0+rdi*8]]
// .L4:
// .quad .L3
// .quad .L5
// .quad .L6
// .L3:
// // 处理0
// jmp .L7
// .L5:
// // 处理1
// jmp .L7
// .L6:
// // 处理2
// jmp .L7
// .L8:
// // 处理默认情况
// .L7:
// ret

// 对于稀疏值,编译器会生成二分查找
void switchSparse(int value) {
switch (value) {
case 0:
// 处理0
break;
case 100:
// 处理100
break;
case 200:
// 处理200
break;
default:
// 处理默认情况
break;
}
}

switch 语句的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 使用switch语句实现状态机
enum class State {
Idle,
Processing,
Completed,
Error
};

void processStateMachine(State& state, Event event) {
switch (state) {
case State::Idle:
if (event == Event::Start) {
state = State::Processing;
startProcessing();
}
break;
case State::Processing:
if (event == Event::Complete) {
state = State::Completed;
finalizeProcessing();
} else if (event == Event::Fail) {
state = State::Error;
handleError();
}
break;
case State::Completed:
if (event == Event::Reset) {
state = State::Idle;
resetState();
}
break;
case State::Error:
if (event == Event::Reset) {
state = State::Idle;
resetState();
}
break;
}
}

// 使用switch语句实现命令模式
class CommandProcessor {
public:
void executeCommand(CommandType type, const CommandData& data) {
switch (type) {
case CommandType::Create:
createResource(data);
break;
case CommandType::Read:
readResource(data);
break;
case CommandType::Update:
updateResource(data);
break;
case CommandType::Delete:
deleteResource(data);
break;
default:
handleUnknownCommand(data);
break;
}
}
private:
// 命令处理方法
void createResource(const CommandData& data);
void readResource(const CommandData& data);
void updateResource(const CommandData& data);
void deleteResource(const CommandData& data);
void handleUnknownCommand(const CommandData& data);
};

逻辑运算符

逻辑运算符的优先级与结合性

运算符优先级结合性描述
!右到左逻辑非
&&左到右逻辑与
||左到右逻辑或

短路求值的深入分析

逻辑运算符具有短路求值的特性,即当表达式的结果已经确定时,不再计算剩余的部分:

1
2
3
4
5
6
7
8
9
10
11
12
// 短路求值示例
int x = 5;

// 如果x > 10为假,不会计算x / 0,避免除零错误
if (x > 10 && (x / 0) == 0) {
// 不会执行到这里
}

// 如果x < 10为真,不会计算x / 0,避免除零错误
if (x < 10 || (x / 0) == 0) {
std::cout << "This will be executed" << std::endl;
}

短路求值的原理

  1. 逻辑与 (&&):当左侧表达式为 false 时,整个表达式的结果必定为 false,因此不再计算右侧表达式。
  2. 逻辑或 (||):当左侧表达式为 true 时,整个表达式的结果必定为 true,因此不再计算右侧表达式。
  3. 逻辑非 (!):没有短路特性,总是计算其操作数。

短路求值的汇编级实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 逻辑与操作的汇编分析
bool logicalAnd(bool a, bool b) {
return a && b;
}

// 对应的x86-64汇编(GCC 11.2,-O2优化)
// logicalAnd(bool, bool):
// test dil, dil
// je .L4
// test sil, sil
// setne al
// ret
// .L4:
// xor eax, eax
// ret

// 逻辑或操作的汇编分析
bool logicalOr(bool a, bool b) {
return a || b;
}

// 对应的x86-64汇编(GCC 11.2,-O2优化)
// logicalOr(bool, bool):
// test dil, dil
// jne .L7
// test sil, sil
// setne al
// ret
// .L7:
// mov eax, 1
// ret

短路求值的高级应用

  1. 安全的空指针检查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 安全地访问指针成员
    if (ptr != nullptr && ptr->value > 0) {
    // 只有当ptr不为空时才访问ptr->value
    }

    // 链式空指针检查
    if (obj && obj->getComponent() && obj->getComponent()->isEnabled()) {
    obj->getComponent()->activate();
    }
  2. 条件函数调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 只有当条件满足时才调用函数
    if (needUpdate && updateData()) {
    // 执行更新后的操作
    }

    // 先验证参数,再调用函数
    if (isValidParam(param) && processParam(param)) {
    // 处理成功
    }
  3. 层级检查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 层级检查,确保每个环节都有效
    if (user != nullptr && user->profile != nullptr && user->profile->address != nullptr) {
    // 访问user->profile->address
    }

    // 使用C++17的std::optional
    if (auto user = getUser(); user && user->profile && user->profile->address) {
    // 访问address
    }
  4. 性能优化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 先检查快速条件,再检查慢速条件
    if (simpleCheck() && expensiveCheck()) {
    // 只有当simpleCheck()为真时才执行expensiveCheck()
    }

    // 先检查常见情况,再检查罕见情况
    if (isCommonCase() || isRareCase()) {
    // 处理
    }
  5. 状态验证链

    1
    2
    3
    4
    5
    6
    7
    // 按顺序验证多个条件
    bool validateInput(const Input& input) {
    return !input.isEmpty() &&
    input.isWithinBounds() &&
    input.isValidFormat() &&
    input.passesSecurityChecks();
    }

短路求值的潜在陷阱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 错误:依赖短路求值的副作用
int i = 0;
if (i < 5 && (i++) < 10) {
// i会递增
}

// 如果修改为||,行为会改变
if (i < 5 || (i++) < 10) {
// i不会递增,因为i < 5为真
}

// 错误:在逻辑表达式中使用有副作用的函数
if (checkCondition() && logAccess()) {
// 如果checkCondition()为假,logAccess()不会执行
// 这可能导致日志记录不完整
}

// 正确:将有副作用的操作移到逻辑表达式之外
if (checkCondition()) {
logAccess();
// 处理
}

逻辑表达式的返回值与类型转换

逻辑表达式返回布尔值,但在C++中,非布尔值也可以用于逻辑表达式,这涉及到隐式类型转换:

1
2
3
4
5
6
7
8
9
10
11
bool result1 = (5 > 3 && 2 < 4); // true
bool result2 = (5 > 3 || 2 > 4); // true
bool result3 = !(5 > 3); // false

// 非布尔值的逻辑表达式
int a = 5; // 非零值为true
int b = 0; // 零值为false

bool result4 = (a && b); // false,因为b为0
bool result5 = (a || b); // true,因为a非零
bool result6 = !a; // false,因为a非零

非布尔值的逻辑转换规则

  1. 整数类型

    • 零值(0)转换为false
    • 非零值转换为true
    • 注意:有符号整数的负值也转换为true
  2. 指针类型

    • 空指针(nullptr0)转换为false
    • 非空指针转换为true
    • 智能指针(std::unique_ptrstd::shared_ptr)也遵循此规则
  3. 浮点类型

    • 零值(0.0)转换为false
    • 非零值转换为true
    • 注意:NaN(非数字)也转换为true
  4. 容器类型(C++20+):

    • 空容器转换为false
    • 非空容器转换为true
    • 支持的容器:std::vectorstd::stringstd::map
  5. 自定义类型

    • 如果类型重载了operator bool(),则使用该运算符的结果
    • 否则,如果类型可以转换为整数、指针等,使用相应的转换规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 指针类型的逻辑表达式
int* ptr = nullptr;
if (ptr) {
std::cout << "ptr is not null" << std::endl;
}

// 智能指针的逻辑表达式
std::unique_ptr<int> uptr;
if (uptr) {
std::cout << "uptr is not null" << std::endl;
}

// 容器类型的逻辑表达式(C++20+)
std::vector<int> v;
if (v) {
std::cout << "v is not empty" << std::endl;
}

// 自定义类型的逻辑表达式
class MyType {
public:
explicit operator bool() const {
return value > 0;
}
private:
int value = 42;
};

MyType obj;
if (obj) {
std::cout << "obj is true" << std::endl;
}

逻辑表达式的返回类型

1
2
3
4
5
6
7
8
9
// 逻辑表达式的返回类型始终是bool
auto result1 = (5 > 3 && 2 < 4); // bool类型
static_assert(std::is_same_v<decltype(result1), bool>);

auto result2 = (5 && 3); // bool类型
static_assert(std::is_same_v<decltype(result2), bool>);

auto result3 = !5; // bool类型
static_assert(std::is_same_v<decltype(result3), bool>);

逻辑运算符的重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 自定义类型重载逻辑运算符
class BooleanLike {
public:
BooleanLike(bool value) : value(value) {}

// 重载逻辑与运算符
BooleanLike operator&&(const BooleanLike& other) const {
return BooleanLike(value && other.value);
}

// 重载逻辑或运算符
BooleanLike operator||(const BooleanLike& other) const {
return BooleanLike(value || other.value);
}

// 重载逻辑非运算符
BooleanLike operator!() const {
return BooleanLike(!value);
}

// 转换为bool
explicit operator bool() const {
return value;
}
private:
bool value;
};

// 使用重载的逻辑运算符
BooleanLike a(true);
BooleanLike b(false);
BooleanLike c = a && b; // false
BooleanLike d = a || b; // true
BooleanLike e = !a; // false

现代C++中的逻辑表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 使用std::optional
std::optional<int> value = getValue();
if (value) {
std::cout << "Value: " << *value << std::endl;
}

// 使用std::variant
std::variant<int, std::string> var = 42;
if (std::holds_alternative<int>(var)) {
std::cout << "int value: " << std::get<int>(var) << std::endl;
}

// 使用概念(C++20+)
template <typename T>
requires std::integral<T> || std::floating_point<T>
bool isPositive(T value) {
return value > 0;
}

// 使用lambda表达式作为条件
auto isEven = [](int n) { return n % 2 == 0; };
if (isEven(42)) {
std::cout << "42 is even" << std::endl;
}

逻辑表达式的性能优化

1. 条件顺序优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 优化前:先执行昂贵的检查
if (expensiveCheck() && commonCondition()) {
// ...
}

// 优化后:先执行快速的常见条件检查
if (commonCondition() && expensiveCheck()) {
// 只有当commonCondition()为真时才执行expensiveCheck()
}

// 优化策略:
// 1. 将快速计算的条件放在前面
// 2. 将可能性大的条件放在前面
// 3. 将副作用小的条件放在前面
// 4. 将缓存友好的条件放在前面

// 示例:先检查内存中的缓存,再检查磁盘
if (cacheContainsData(key) && diskContainsData(key)) {
// 使用数据
}

2. 逻辑表达式的简化与重构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 德摩根定律简化
// 原表达式
if (!(a && b && c)) {
// ...
}

// 简化后
if (!a || !b || !c) {
// ...
}

// 提取重复条件到变量
// 优化前
if (user.hasPermission(Permission::READ) && user.hasPermission(Permission::WRITE)) {
// ...
}

// 优化后
bool hasReadWrite = user.hasPermission(Permission::READ) && user.hasPermission(Permission::WRITE);
if (hasReadWrite) {
// ...
}

// 使用布尔代数简化
// 优化前
if (x > 0 && y > 0 || x < 0 && y < 0) {
// 同号
}

// 优化后
if (x * y > 0) {
// 同号
}

// 使用命名函数提高可读性
bool isPositiveProduct(int x, int y) {
return x * y > 0;
}

if (isPositiveProduct(x, y)) {
// 同号
}

3. 避免不必要的计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 缓存计算结果
// 优化前
if (getUserRole(userId) == Role::Admin && getUserPermissions(userId).contains(Permission::DELETE)) {
// ...
}

// 优化后
auto role = getUserRole(userId);
if (role == Role::Admin) {
auto permissions = getUserPermissions(userId);
if (permissions.contains(Permission::DELETE)) {
// ...
}
}

// 避免在逻辑表达式中执行有副作用的操作
// 优化前
if (checkCondition() && logAccess()) {
// 如果checkCondition()为假,logAccess()不会执行
}

// 优化后
if (checkCondition()) {
logAccess(); // 确保日志被记录
// ...
}

// 使用缓存避免重复计算
class DataProcessor {
private:
mutable std::optional<bool> validityCache;

public:
bool isValid() const {
if (!validityCache) {
validityCache = expensiveValidation();
}
return *validityCache;
}

void invalidateCache() {
validityCache.reset();
}
};

4. 位运算替代逻辑运算(适用于特定场景)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 逻辑运算
bool hasAllPermissions = hasRead && hasWrite && hasExecute;

// 位运算(适用于权限标志)
enum Permission {
READ = 1 << 0, // 0b001
WRITE = 1 << 1, // 0b010
EXECUTE = 1 << 2 // 0b100
};

int userPermissions = READ | WRITE;
bool hasAllPermissions = (userPermissions & (READ | WRITE | EXECUTE)) == (READ | WRITE | EXECUTE);

// 位运算通常比逻辑运算更快,尤其是在处理多个标志时

5. 编译时优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 使用constexpr在编译时计算
constexpr bool isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}

// 编译时计算条件
if constexpr (isPowerOfTwo(16)) {
// 编译时确定为真的代码
}

// 使用模板元编程在编译时优化
template <bool Condition>
void process() {
if constexpr (Condition) {
// 条件为真时的代码
} else {
// 条件为假时的代码
}
}

6. 分支预测优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 分支预测友好的代码:将常见情况放在前面
if (isCommonCase) {
// 处理常见情况
} else {
// 处理罕见情况
}

// 避免不可预测的分支
// 不好的做法:随机条件导致分支预测失败
if (rand() % 2 == 0) {
// ...
} else {
// ...
}

// 好的做法:使用查表代替条件分支
int lookupTable[] = {0, 1, 2, 3};
int result = lookupTable[index]; // 无分支操作

// 好的做法:使用条件移动指令代替分支
int max(int a, int b) {
return a > b ? a : b;
// 现代编译器会生成条件移动指令,无分支
}

7. 逻辑表达式的向量化优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 使用SIMD指令优化逻辑表达式
// 注意:需要编译器支持和适当的编译选项
#include <immintrin.h>

// 向量化逻辑与操作
void vectorizedLogicalAnd(const bool* a, const bool* b, bool* result, size_t size) {
size_t i = 0;
// 向量化处理
for (; i + 15 < size; i += 16) {
__m128i va = _mm_loadu_si128(reinterpret_cast<const __m128i*>(a + i));
__m128i vb = _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
__m128i vresult = _mm_and_si128(va, vb);
_mm_storeu_si128(reinterpret_cast<__m128i*>(result + i), vresult);
}
// 处理剩余部分
for (; i < size; ++i) {
result[i] = a[i] && b[i];
}
}

// 向量化逻辑或操作
void vectorizedLogicalOr(const bool* a, const bool* b, bool* result, size_t size) {
size_t i = 0;
// 向量化处理
for (; i + 15 < size; i += 16) {
__m128i va = _mm_loadu_si128(reinterpret_cast<const __m128i*>(a + i));
__m128i vb = _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
__m128i vresult = _mm_or_si128(va, vb);
_mm_storeu_si128(reinterpret_cast<__m128i*>(result + i), vresult);
}
// 处理剩余部分
for (; i < size; ++i) {
result[i] = a[i] || b[i];
}
}

现代C++中的逻辑表达式

1. nullptr的使用与空值检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 传统C++的空值检查
if (ptr != NULL) {
// ...
}

// 现代C++推荐使用nullptr
if (ptr != nullptr) {
// ...
}

// 更简洁的写法
if (ptr) {
// ...
}

// 结合智能指针
if (auto sp = std::make_shared<Resource>(); sp) {
// 使用sp
}

// 空值检查的最佳实践
template <typename T>
bool isNotNull(const T* ptr) {
return ptr != nullptr;
}

// 使用std::pointer_traits进行类型无关的空值检查
template <typename Ptr>
bool isPtrNotNull(const Ptr& ptr) {
return ptr != std::pointer_traits<Ptr>::null();
}

2. std::optional的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 使用std::optional进行空值检查
std::optional<int> value = getValue();
if (value) {
std::cout << "Value: " << *value << std::endl;
}

// 使用std::optional的value_or方法
int defaultValue = 42;
int result = value.value_or(defaultValue);

// 使用std::optional的and_then进行链式操作
std::optional<int> processValue(std::optional<int> opt) {
return opt
.and_then([](int x) { return x > 0 ? std::optional<int>(x * 2) : std::nullopt; })
.or_else([]() { return std::optional<int>(0); });
}

// 使用std::optional进行错误处理
std::optional<std::string> parseInput(const std::string& input) {
if (input.empty()) {
return std::nullopt;
}
return input;
}

if (auto result = parseInput(userInput); result) {
// 处理成功
} else {
// 处理错误
}

3. std::variant的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 使用std::variant进行类型检查
std::variant<int, double, std::string> var = 42;

// 使用std::holds_alternative进行类型检查
if (std::holds_alternative<int>(var)) {
std::cout << "int value: " << std::get<int>(var) << std::endl;
}

// 使用std::visit进行类型分发
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "string: " << arg << std::endl;
}
}, var);

// 使用std::get_if进行指针式访问
if (auto* intPtr = std::get_if<int>(&var)) {
std::cout << "int value: " << *intPtr << std::endl;
}

4. 概念的使用(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 使用概念进行编译时类型检查
template <typename T>
requires std::integral<T>
void processIntegral(T value) {
// 处理整数类型
}

// 组合多个概念
template <typename T>
requires std::integral<T> && std::signed_integral<T>
void processSignedIntegral(T value) {
// 处理有符号整数类型
}

// 自定义概念
template <typename T>
concept Arithmetic = std::integral<T> || std::floating_point<T>;

template <Arithmetic T>
T add(T a, T b) {
return a + b;
}

// 概念的逻辑组合
template <typename T>
requires Arithmetic<T> && (!std::same_as<T, bool>)
T multiply(T a, T b) {
return a * b;
}

5. 协程中的逻辑表达式(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 协程中的条件检查
#include <coroutine>
#include <future>

std::future<int> processData(std::optional<int> data) {
if (!data) {
co_return 0;
}

// 处理数据
co_return *data * 2;
}

// 协程中的错误处理
std::future<void> performTask(bool shouldFail) {
if (shouldFail) {
throw std::runtime_error("Task failed");
}
// 执行任务
co_return;
}

6. 范围库中的逻辑表达式(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 使用范围库进行条件过滤
#include <ranges>
#include <vector>

std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 过滤偶数
auto evenNumbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });

// 过滤大于5的数
auto greaterThan5 = numbers | std::views::filter([](int n) { return n > 5; });

// 组合条件
auto evenAndGreaterThan5 = numbers |
std::views::filter([](int n) { return n % 2 == 0 && n > 5; });

// 使用谓词函数
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return false;
}
return true;
}

auto primes = numbers | std::views::filter(isPrime);

7. 模块中的逻辑表达式(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 模块中的条件编译
export module MyModule;

import std;

export namespace MyModule {
// 条件导出
#if defined(ENABLE_FEATURE_X)
export void featureX() {
// 实现
}
#endif

// 运行时条件检查
export bool isFeatureEnabled() {
return std::getenv("FEATURE_ENABLED") != nullptr;
}
}

关系运算符

关系运算符的优先级与结合性

运算符优先级结合性描述
<, <=, >, >=中高左到右大小比较
==, !=左到右相等性比较

关系表达式的返回值与计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 关系表达式返回布尔值
bool result1 = (5 > 3); // true
bool result2 = (5 == 3); // false
bool result3 = (5 != 3); // true

// 连续比较的陷阱
int a = 1, b = 2, c = 3;
bool result4 = (a < b < c); // 不是数学中的连续比较
// 实际计算:(a < b) < c → true < c → 1 < 3 → true

// 正确的连续比较
bool result5 = (a < b && b < c); // true

// 关系表达式的操作数转换
// 算术类型会进行常规算术转换
int i = 5;
double d = 5.0;
bool equal = (i == d); // true,i被转换为double

// 指针类型的比较
int arr[5] = {1, 2, 3, 4, 5};
int* p1 = &arr[0];
int* p2 = &arr[1];
bool less = (p1 < p2); // true,指向数组前面元素的指针小于后面的

关系运算符的安全性

1. 整数比较的安全性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 有符号整数与无符号整数比较的陷阱
int a = -1;
unsigned int b = 1;
if (a < b) { // 错误:a会被转换为无符号整数,变成很大的正数
std::cout << "a < b" << std::endl;
} else {
std::cout << "a >= b" << std::endl; // 会执行这里
}

// 正确的比较方法:显式类型转换
if (static_cast<long long>(a) < static_cast<long long>(b)) {
std::cout << "a < b" << std::endl; // 会执行这里
}

// 整数溢出导致的比较错误
int x = INT_MAX;
int y = x + 1; // 溢出,行为未定义
if (y < x) {
std::cout << "y < x" << std::endl; // 可能执行这里
}

// 安全的整数比较
template <typename T>
requires std::integral<T>
bool safeLess(T a, T b) {
// 对于有符号整数,检查溢出
if constexpr (std::is_signed_v<T>) {
return (b > 0 && a < b - a) || (b < 0 && a < b);
} else {
return a < b;
}
}

2. 浮点数比较的安全性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 浮点数比较的陷阱
double x = 0.1;
double y = 0.3 / 3.0;

// 错误:直接比较
if (x == y) {
std::cout << "x == y" << std::endl;
} else {
std::cout << "x != y" << std::endl; // 可能执行这里
}

// 正确:使用容差比较
const double EPSILON = 1e-9;
if (std::abs(x - y) < EPSILON) {
std::cout << "x approximately equals y" << std::endl;
}

// 更健壮的浮点数比较函数
bool approximatelyEqual(double a, double b, double epsilon = 1e-9) {
return std::abs(a - b) < epsilon;
}

// 相对误差比较(适用于大范围的数值)
bool relativelyEqual(double a, double b, double epsilon = 1e-9) {
double maxAbs = std::max(std::abs(a), std::abs(b));
return std::abs(a - b) <= maxAbs * epsilon;
}

// 处理NaN和无穷大
bool safeFloatEqual(double a, double b) {
if (std::isnan(a) || std::isnan(b)) {
return std::isnan(a) && std::isnan(b);
}
if (std::isinf(a) || std::isinf(b)) {
return std::isinf(a) == std::isinf(b) && (a > 0) == (b > 0);
}
return approximatelyEqual(a, b);
}

3. 指针比较的安全性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 指针比较的规则
int arr[5] = {1, 2, 3, 4, 5};
int* p1 = &arr[0];
int* p2 = &arr[1];

// 安全:指向同一数组的指针可以比较
if (p1 < p2) {
std::cout << "p1 points to an earlier element" << std::endl;
}

// 不安全:指向不同对象的指针比较
int x = 5;
int y = 10;
int* px = &x;
int* py = &y;
// if (px < py) { // 未定义行为
// ...
// }

// 安全:空指针可以与任何指针比较
int* nullPtr = nullptr;
if (px != nullPtr) {
std::cout << "px is not null" << std::endl;
}

// 安全:使用std::less进行指针比较(即使指向不同对象)
if (std::less<int*>()(px, py)) {
std::cout << "px is considered less than py" << std::endl;
}

4. 自定义类型的比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 自定义类型的比较运算符重载
class Point {
public:
int x, y;

Point(int x, int y) : x(x), y(y) {}

// 重载等于运算符
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}

// 重载不等于运算符
bool operator!=(const Point& other) const {
return !(*this == other);
}

// 重载小于运算符(用于排序)
bool operator<(const Point& other) const {
if (x != other.x) return x < other.x;
return y < other.y;
}
};

// 使用自定义类型的比较
Point p1(1, 2);
Point p2(3, 4);
if (p1 < p2) {
std::cout << "p1 is less than p2" << std::endl;
}

// 使用std::tuple进行多字段比较
bool comparePoints(const Point& a, const Point& b) {
return std::make_tuple(a.x, a.y) < std::make_tuple(b.x, b.y);
}

现代C++中的比较运算符

1. 三路比较运算符(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 使用三路比较运算符(太空船运算符)
auto result = a <=> b;

if (result < 0) {
std::cout << "a < b" << std::endl;
} else if (result == 0) {
std::cout << "a == b" << std::endl;
} else {
std::cout << "a > b" << std::endl;
}

// 三路比较运算符的返回类型
// 对于整数类型,返回std::strong_ordering
// 对于浮点类型,返回std::partial_ordering(因为有NaN)
// 对于指针类型,返回std::weak_ordering

// 使用std::compare_three_way进行统一比较
#include <compare>

int compareValues(int a, int b) {
auto cmp = std::compare_three_way{}(a, b);
if (cmp < 0) return -1;
if (cmp > 0) return 1;
return 0;
}

2. 默认比较(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 使用默认比较
struct Point {
int x;
int y;

// 默认生成所有比较运算符
auto operator<=>(const Point&) const = default;
};

Point p1{1, 2};
Point p2{3, 4};

if (p1 < p2) {
std::cout << "p1 < p2" << std::endl;
}

// 默认比较的规则
// 1. 成员按声明顺序进行比较
// 2. 对每个成员使用其对应的<=>运算符
// 3. 如果所有成员相等,则返回0
// 4. 否则返回第一个不相等成员的比较结果

// 同时默认生成==运算符
struct Rectangle {
int width;
int height;

// 默认生成所有比较运算符,包括==
auto operator<=>(const Rectangle&) const = default;
};

Rectangle r1{10, 20};
Rectangle r2{10, 20};
if (r1 == r2) {
std::cout << "r1 == r2" << std::endl;
}

3. 太空船运算符的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 自定义类型的比较
class Person {
public:
std::string name;
int age;

// 自定义三路比较运算符
auto operator<=>(const Person& other) const {
// 先比较name,再比较age
if (auto cmp = name <=> other.name; cmp != 0) {
return cmp;
}
return age <=> other.age;
}

// 显式定义==运算符(如果需要自定义)
bool operator==(const Person& other) const {
return name == other.name && age == other.age;
}
};

// 使用std::tuple进行多字段比较
class Employee {
public:
std::string name;
int id;
double salary;

auto operator<=>(const Employee& other) const {
// 使用tuple的三路比较
return std::tie(name, id, salary) <=> std::tie(other.name, other.id, other.salary);
}
};

// 比较运算符的继承
struct Base {
int value;
auto operator<=>(const Base&) const = default;
};

struct Derived : Base {
int derivedValue;

auto operator<=>(const Derived& other) const {
// 先比较基类部分,再比较派生类部分
if (auto cmp = static_cast<const Base&>(*this) <=> static_cast<const Base&>(other); cmp != 0) {
return cmp;
}
return derivedValue <=> other.derivedValue;
}
};

4. 比较类别(C++20+)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 比较类别的使用
#include <compare>

// 强序关系:所有值都可比较,且相等性与等价性一致
std::strong_ordering compareStrong(int a, int b) {
return a <=> b;
}

// 弱序关系:所有值都可比较,但相等性可能与等价性不一致(如浮点数)
std::weak_ordering compareWeak(double a, double b) {
if (std::isnan(a) || std::isnan(b)) {
return std::weak_ordering::equivalent;
}
return a <=> b;
}

// 偏序关系:不是所有值都可比较(如浮点数的NaN)
std::partial_ordering comparePartial(double a, double b) {
return a <=> b;
}

// 比较类别的特性
// - std::strong_ordering: 支持 <, <=, >, >=, ==, !=
// - std::weak_ordering: 支持 <, <=, >, >=, ==, !=
// - std::partial_ordering: 支持 <, <=, >, >=, ==, !=, 和 <=> 的特殊值

5. 比较运算符的最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 比较运算符的最佳实践
class Date {
public:
int year, month, day;

// 使用默认比较
auto operator<=>(const Date&) const = default;
};

// 为不可比较类型定义比较
class Complex {
public:
double real, imag;

// 复数不支持全序比较,只支持相等性比较
bool operator==(const Complex& other) const {
return real == other.real && imag == other.imag;
}

// 可以定义模长比较
bool operator<(const Complex& other) const {
return std::hypot(real, imag) < std::hypot(other.real, other.imag);
}
};

// 使用命名比较函数
template <typename T>
bool isLessThan(const T& a, const T& b) {
return a < b;
}

// 使用std::lexicographical_compare进行字典序比较
#include <algorithm>

bool lexCompare(const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(),
b.begin(), b.end()
);
}

关系表达式的最佳实践

1. 使用命名常量和枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 使用命名常量提高可读性
const int MIN_AGE = 18;
const int MAX_AGE = 65;

if (age >= MIN_AGE && age <= MAX_AGE) {
// ...
}

// 使用枚举提高可读性和类型安全性
enum class Status {
Inactive,
Active,
Suspended
};

if (userStatus == Status::Active) {
// ...
}

// 使用C++11的强类型枚举
enum class ErrorCode : int {
Success = 0,
InvalidInput = 1,
NetworkError = 2,
DatabaseError = 3
};

if (error == ErrorCode::Success) {
// ...
}

// 使用constexpr定义编译时常量
constexpr int MAX_RETRY_COUNT = 3;
constexpr double PI = 3.14159265358979323846;

if (retryCount < MAX_RETRY_COUNT) {
// ...
}

2. 提取复杂条件到函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 提取复杂条件到函数
bool isEligible(int age, bool hasLicense, bool hasInsurance) {
return age >= 18 && hasLicense && hasInsurance;
}

if (isEligible(userAge, userHasLicense, userHasInsurance)) {
// ...
}

// 使用lambda表达式提取临时条件
auto isAdult = [](int age) { return age >= 18; };
auto hasValidLicense = [&]() { return user.hasLicense() && user.licenseIsValid(); };

if (isAdult(user.getAge()) && hasValidLicense()) {
// ...
}

// 提取业务规则到单独的函数
bool isUserAuthorized(const User& user, const Resource& resource) {
if (!user.isLoggedIn()) return false;
if (user.isAdmin()) return true;
if (!resource.isAccessible()) return false;
return user.hasPermission(resource.getRequiredPermission());
}

if (isUserAuthorized(currentUser, requestedResource)) {
// ...
}

3. 避免魔法数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 避免魔法数字
if (score >= 90) { // 90是魔法数字
// ...
}

// 更好的做法:使用命名常量
const int PASSING_SCORE = 60;
const int EXCELLENT_SCORE = 90;

if (score >= EXCELLENT_SCORE) {
// ...
}

// 使用结构体组织相关常量
struct ScoreThresholds {
static constexpr int EXCELLENT = 90;
static constexpr int GOOD = 80;
static constexpr int AVERAGE = 70;
static constexpr int PASSING = 60;
};

if (score >= ScoreThresholds::EXCELLENT) {
// ...
}

// 使用配置类管理阈值
class Configuration {
public:
static int getMinimumAge() { return 18; }
static int getMaximumRetries() { return 3; }
static double getTolerance() { return 1e-9; }
};

if (age >= Configuration::getMinimumAge()) {
// ...
}

4. 使用有意义的变量名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 不好的做法:使用简短的变量名
if (a < b && c > d) {
// ...
}

// 好的做法:使用有意义的变量名
bool isTemperatureWithinRange = currentTemp >= minTemp && currentTemp <= maxTemp;
bool isHumidityAcceptable = currentHumidity < maxHumidity;

if (isTemperatureWithinRange && isHumidityAcceptable) {
// ...
}

// 使用布尔变量提高可读性
bool userIsActive = user.status == UserStatus::Active;
bool userHasPermission = user.permissions.contains(Permission::Write);
bool resourceIsAvailable = resource.state == ResourceState::Available;

if (userIsActive && userHasPermission && resourceIsAvailable) {
// ...
}

5. 简化复杂的关系表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 复杂的关系表达式
if (x > 0 && x < 100 && y > 0 && y < 100 && z > 0 && z < 100) {
// ...
}

// 简化:提取到函数
bool isPointInCube(int x, int y, int z, int size) {
auto isInRange = [size](int value) { return value > 0 && value < size; };
return isInRange(x) && isInRange(y) && isInRange(z);
}

if (isPointInCube(x, y, z, 100)) {
// ...
}

// 使用标准库函数简化
#include <algorithm>

std::vector<int> values = {1, 2, 3, 4, 5};
int target = 3;

// 检查target是否在values中
if (std::find(values.begin(), values.end(), target) != values.end()) {
// ...
}

// C++20:使用std::ranges
#include <ranges>

if (std::ranges::contains(values, target)) {
// ...
}

6. 关系表达式的性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 优化前:重复计算
if (calculateValue() > threshold && calculateValue() < maxThreshold) {
// ...
}

// 优化后:缓存计算结果
auto value = calculateValue();
if (value > threshold && value < maxThreshold) {
// ...
}

// 优化条件顺序:先检查快速条件
if (quickCheck() && expensiveCheck()) {
// ...
}

// 使用位掩码提高性能
const int PERMISSION_READ = 1 << 0;
const int PERMISSION_WRITE = 1 << 1;
const int PERMISSION_EXECUTE = 1 << 2;

int userPermissions = PERMISSION_READ | PERMISSION_WRITE;
if ((userPermissions & (PERMISSION_READ | PERMISSION_WRITE)) == (PERMISSION_READ | PERMISSION_WRITE)) {
// ...
}

// 使用查表代替范围检查
constexpr bool isVowel(char c) {
static constexpr bool vowels[] = {
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, true, false, false, false, true, false, false,
false, true, false, false, false, true, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, true, false, false, false, true, false, false,
false, true, false, false, false, true, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, true, false, false, false, true, false, false,
false, true, false, false, false, true, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false
};
return vowels[static_cast<unsigned char>(c)];
}

if (isVowel(ch)) {
// ...
}

条件运算符

条件运算符的基本用法与嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 基本条件运算符
int a = 10, b = 20;
int max = (a > b) ? a : b;
std::cout << "Max: " << max << std::endl;

// 嵌套条件运算符
int a = 10, b = 20, c = 30;
int max = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
std::cout << "Max: " << max << std::endl;

// 可读性更好的写法
int maxValue = std::max({a, b, c});

// 嵌套条件运算符的可读性问题
// 不好的写法:过于复杂的嵌套
std::string grade = (score >= 90) ? "A" :
(score >= 80) ? "B" :
(score >= 70) ? "C" :
(score >= 60) ? "D" : "F";

// 好的写法:使用if-else或函数
std::string getGrade(int score) {
if (score >= 90) return "A";
if (score >= 80) return "B";
if (score >= 70) return "C";
if (score >= 60) return "D";
return "F";
}

条件运算符与表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 条件运算符用于表达式
std::string result = (score >= 60) ? "Pass" : "Fail";
std::cout << "Result: " << result << std::endl;

// 条件运算符用于函数参数
printGrade((score >= 90) ? 'A' : (score >= 80) ? 'B' : (score >= 70) ? 'C' : (score >= 60) ? 'D' : 'F');

// 条件运算符用于初始化
int value = (condition) ? 42 : 0;

// 条件运算符用于返回值
int getValue(bool flag) {
return flag ? 100 : 200;
}

// 条件运算符与类型推导
auto result = (condition) ? 42 : 3.14; // 类型为double

// 条件运算符与引用
int x = 10, y = 20;
int& ref = (condition) ? x : y;
ref = 30; // 修改x或y的值

条件运算符的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 条件运算符与lambda表达式
auto func = (condition) ?
[]() { std::cout << "True branch" << std::endl; } :
[]() { std::cout << "False branch" << std::endl; };
func();

// 条件运算符与智能指针
std::unique_ptr<Resource> createResource(bool useAdvanced) {
return useAdvanced ?
std::make_unique<AdvancedResource>() :
std::make_unique<BasicResource>();
}

// 条件运算符与std::optional
std::optional<int> getOptionalValue(bool hasValue) {
return hasValue ? std::optional<int>(42) : std::nullopt;
}

// 条件运算符与std::variant
std::variant<int, std::string> getVariant(bool useInt) {
return useInt ? std::variant<int, std::string>(42) : std::variant<int, std::string>("forty-two");
}

条件运算符的性能考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 条件运算符的性能
// 简单类型的条件运算符通常会被编译器优化为条件移动指令
int result = (a > b) ? a : b;

// 复杂表达式的条件运算符
// 注意:两个分支的表达式都会被求值吗?
// 不,条件运算符也有短路特性
int result = (condition) ? expensiveFunction() : 0;
// 只有当condition为真时,才会调用expensiveFunction()

// 条件运算符与分支预测
// 对于可预测的条件,条件运算符和if-else性能相似
// 对于不可预测的条件,条件运算符可能生成更优的代码

// 编译器优化示例
// 以下代码可能被编译器优化为查表操作
char getGrade(int score) {
return (score >= 90) ? 'A' :
(score >= 80) ? 'B' :
(score >= 70) ? 'C' :
(score >= 60) ? 'D' : 'F';
}

条件运算符的最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 最佳实践:保持条件运算符简洁
// 好的写法:简单的条件判断
int max = (a > b) ? a : b;

// 不好的写法:过于复杂的条件
int result = (a > b && c < d || e == f) ? (g + h) : (i - j);

// 最佳实践:提取复杂条件到变量
bool condition = a > b && c < d || e == f;
int value1 = g + h;
int value2 = i - j;
int result = condition ? value1 : value2;

// 最佳实践:避免在条件运算符中使用有副作用的表达式
// 不好的写法:有副作用
int i = 0;
int result = (i++ > 0) ? i : 0;

// 好的写法:将副作用移到外面
int i = 0;
bool condition = i++ > 0;
int result = condition ? i : 0;

// 最佳实践:使用条件运算符进行空值检查
std::string getName(const User* user) {
return user ? user->getName() : "Unknown";
}

// C++17:使用if语句的初始化语句代替复杂的条件运算符
if (auto user = getUser(); user) {
processUser(user);
} else {
handleNoUser();
}

条件运算符与现代C++特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// C++17:结构化绑定与条件运算符
struct Point { int x, y; };

Point p1 = {1, 2};
Point p2 = {3, 4};

auto [x, y] = (condition) ? p1 : p2;

// C++20:三路比较运算符与条件运算符
auto cmp = a <=> b;
int result = (cmp < 0) ? -1 : (cmp > 0) ? 1 : 0;

// C++20:范围库与条件运算符
auto range = (useEven) ?
numbers | std::views::filter([](int n) { return n % 2 == 0; }) :
numbers | std::views::filter([](int n) { return n % 2 != 0; });

// C++23:std::expected与条件运算符
std::expected<int, std::string> divide(int a, int b) {
return (b == 0) ?
std::unexpected(std::string("Division by zero")) :
std::expected<int, std::string>(a / b);
}

逻辑运算符的应用

1. 范围检查的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 基本范围检查
bool isInRange(int value, int min, int max) {
return (value >= min && value <= max);
}

// 使用示例
if (isInRange(age, 18, 65)) {
std::cout << "Age is in valid range" << std::endl;
}

// 高级范围检查:包含边界检查
class Range {
private:
int min_;
int max_;
public:
Range(int min, int max) : min_(min), max_(max) {}

bool contains(int value) const {
return value >= min_ && value <= max_;
}

bool overlaps(const Range& other) const {
return contains(other.min_) || contains(other.max_) ||
other.contains(min_) || other.contains(max_);
}
};

// 使用Range类
Range adultAge(18, 65);
if (adultAge.contains(30)) {
std::cout << "30 is in adult age range" << std::endl;
}

// 模板版本的范围检查
template <typename T>
requires std::totally_ordered<T>
bool isInRange(const T& value, const T& min, const T& max) {
return value >= min && value <= max;
}

// 使用模板版本
if (isInRange<double>(3.14, 0.0, 10.0)) {
std::cout << "3.14 is in range [0.0, 10.0]" << std::endl;
}

2. 多重条件检查的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 基本用户验证
bool isValidUser(const std::string& username, const std::string& password) {
return (!username.empty() && !password.empty() && password.length() >= 8);
}

// 高级用户验证:包含复杂规则
class UserValidator {
public:
static bool isValidUsername(const std::string& username) {
return !username.empty() && username.length() >= 3 && username.length() <= 20;
}

static bool isValidPassword(const std::string& password) {
if (password.length() < 8) return false;

bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;
for (char c : password) {
if (std::isupper(c)) hasUpper = true;
else if (std::islower(c)) hasLower = true;
else if (std::isdigit(c)) hasDigit = true;
else if (std::ispunct(c)) hasSpecial = true;
}

return hasUpper && hasLower && hasDigit && hasSpecial;
}

static bool isValidUser(const std::string& username, const std::string& password) {
return isValidUsername(username) && isValidPassword(password);
}
};

// 使用示例
if (UserValidator::isValidUser(user, pass)) {
std::cout << "Login successful" << std::endl;
} else {
std::cout << "Invalid username or password" << std::endl;
}

// 使用lambda表达式进行条件验证
auto validateInput = [](const std::string& input) {
return !input.empty() &&
std::all_of(input.begin(), input.end(), ::isdigit) &&
input.length() == 6;
};

if (validateInput(zipCode)) {
std::cout << "Valid zip code" << std::endl;
}

3. 状态检查的高级应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// 基本系统状态检查
bool isSystemReady(bool networkUp, bool databaseUp, bool servicesRunning) {
return (networkUp && databaseUp && servicesRunning);
}

// 高级系统状态检查:包含详细状态
class SystemStatus {
public:
enum class ComponentStatus {
Up,
Down,
Degraded
};

SystemStatus(ComponentStatus network, ComponentStatus database, ComponentStatus services)
: network_(network), database_(database), services_(services) {}

bool isFullyOperational() const {
return network_ == ComponentStatus::Up &&
database_ == ComponentStatus::Up &&
services_ == ComponentStatus::Up;
}

bool isPartiallyOperational() const {
return network_ != ComponentStatus::Down ||
database_ != ComponentStatus::Down ||
services_ != ComponentStatus::Down;
}

bool isCritical() const {
return network_ == ComponentStatus::Down ||
database_ == ComponentStatus::Down;
}

std::string getStatusMessage() const {
if (isFullyOperational()) {
return "System is fully operational";
} else if (isCritical()) {
return "System is in critical state";
} else if (isPartiallyOperational()) {
return "System is partially operational";
} else {
return "System is completely down";
}
}
private:
ComponentStatus network_;
ComponentStatus database_;
ComponentStatus services_;
};

// 使用示例
SystemStatus status(SystemStatus::ComponentStatus::Up,
SystemStatus::ComponentStatus::Up,
SystemStatus::ComponentStatus::Degraded);

if (status.isFullyOperational()) {
std::cout << "System is ready" << std::endl;
} else {
std::cout << status.getStatusMessage() << std::endl;
}

// 状态检查与策略模式
class StatusChecker {
public:
virtual ~StatusChecker() = default;
virtual bool check() const = 0;
};

class NetworkChecker : public StatusChecker {
public:
bool check() const override {
// 检查网络状态
return true;
}
};

class DatabaseChecker : public StatusChecker {
public:
bool check() const override {
// 检查数据库状态
return true;
}
};

class CompositeStatusChecker {
public:
void addChecker(std::unique_ptr<StatusChecker> checker) {
checkers_.push_back(std::move(checker));
}

bool checkAll() const {
return std::all_of(checkers_.begin(), checkers_.end(),
[](const auto& checker) { return checker->check(); });
}

bool checkAny() const {
return std::any_of(checkers_.begin(), checkers_.end(),
[](const auto& checker) { return checker->check(); });
}
private:
std::vector<std::unique_ptr<StatusChecker>> checkers_;
};

4. 逻辑运算符在设计模式中的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// 责任链模式中的条件检查
class Handler {
public:
virtual ~Handler() = default;
void setNext(std::unique_ptr<Handler> next) {
next_ = std::move(next);
}

bool handle(const Request& request) {
if (canHandle(request)) {
return process(request);
} else if (next_) {
return next_->handle(request);
} else {
return false;
}
}
protected:
virtual bool canHandle(const Request& request) const = 0;
virtual bool process(const Request& request) = 0;
std::unique_ptr<Handler> next_;
};

// 策略模式中的条件选择
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(std::vector<int>& data) = 0;
};

class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// 冒泡排序实现
}
};

class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// 快速排序实现
}
};

class SortContext {
public:
void setStrategy(std::unique_ptr<SortStrategy> strategy) {
strategy_ = std::move(strategy);
}

void sort(std::vector<int>& data) {
if (strategy_) {
strategy_->sort(data);
}
}
private:
std::unique_ptr<SortStrategy> strategy_;
};

// 根据数据大小选择排序策略
void selectSortStrategy(SortContext& context, const std::vector<int>& data) {
if (data.size() < 100) {
context.setStrategy(std::make_unique<BubbleSort>());
} else {
context.setStrategy(std::make_unique<QuickSort>());
}
}

分支语句的最佳实践

1. 代码可读性的专业实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 不好的写法:缩进不一致,缺少空格
if(x>0&&y<10){
for(int i=0;i<5;i++){
std::cout<<i;
}}

// 好的写法:一致的缩进,适当的空格
if (x > 0 && y < 10) {
for (int i = 0; i < 5; ++i) {
std::cout << i;
}
}

// 不好的写法:复杂条件缺少注释
if ((userRole == Admin || userRole == Moderator) &&
(action == Create || action == Edit) &&
!isRestricted(resourceId)) {
// ...
}

// 好的写法:添加注释,使用换行提高可读性
// 检查用户是否有权限执行操作
if ((userRole == Admin || userRole == Moderator) && // 管理员或版主
(action == Create || action == Edit) && // 创建或编辑操作
!isRestricted(resourceId)) { // 资源未被限制
// ...
}

// 不好的写法:缺少大括号
if (condition)
doSomething();
else
doSomethingElse();

// 好的写法:始终使用大括号
if (condition) {
doSomething();
} else {
doSomethingElse();
}

2. 避免深度嵌套的高级技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 不好的写法:深度嵌套
void processOrder(const Order& order) {
if (order.isValid()) {
if (order.isPaid()) {
if (order.isShippable()) {
if (hasInventory(order)) {
shipOrder(order);
} else {
notifyOutOfStock(order);
}
} else {
notifyCannotShip(order);
}
} else {
notifyUnpaid(order);
}
} else {
notifyInvalidOrder(order);
}
}

// 好的写法:使用早期返回
void processOrder(const Order& order) {
if (!order.isValid()) {
notifyInvalidOrder(order);
return;
}

if (!order.isPaid()) {
notifyUnpaid(order);
return;
}

if (!order.isShippable()) {
notifyCannotShip(order);
return;
}

if (hasInventory(order)) {
shipOrder(order);
} else {
notifyOutOfStock(order);
}
}

// 好的写法:提取嵌套逻辑为函数
bool canProcessOrder(const Order& order) {
return order.isValid() && order.isPaid() && order.isShippable();
}

void handleInventory(const Order& order) {
if (hasInventory(order)) {
shipOrder(order);
} else {
notifyOutOfStock(order);
}
}

void processOrder(const Order& order) {
if (!canProcessOrder(order)) {
handleOrderIssues(order);
return;
}

handleInventory(order);
}

3. 条件表达式的简化策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 不好的写法:使用魔法数字
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} // ...

// 好的写法:使用命名常量
const int EXCELLENT_SCORE = 90;
const int GOOD_SCORE = 80;
// ...
if (score >= EXCELLENT_SCORE) {
grade = 'A';
} else if (score >= GOOD_SCORE) {
grade = 'B';
} // ...

// 不好的写法:使用整数常量表示状态
if (status == 1) {
// 处理活跃状态
} else if (status == 2) {
// 处理禁用状态
}

// 好的写法:使用枚举类型
enum class Status {
Inactive = 0,
Active = 1,
Suspended = 2
};

if (status == Status::Active) {
// 处理活跃状态
} else if (status == Status::Suspended) {
// 处理禁用状态
}

// 不好的写法:复杂的条件表达式
if (user.isLoggedIn() && user.hasPermission(Permission::WRITE) && resource.isAvailable()) {
// ...
}

// 好的写法:使用布尔变量提高可读性
bool userCanWrite = user.isLoggedIn() && user.hasPermission(Permission::WRITE);
bool resourceReady = resource.isAvailable();

if (userCanWrite && resourceReady) {
// ...
}

4. switch 语句的专家级最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 不好的写法:缺少default分支
enum class Day {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
};

void printDay(Day day) {
switch (day) {
case Day::Monday:
std::cout << "Monday" << std::endl;
break;
// 缺少其他case和default
}
}

// 好的写法:包含所有case和default分支
void printDay(Day day) {
switch (day) {
case Day::Monday:
std::cout << "Monday" << std::endl;
break;
case Day::Tuesday:
std::cout << "Tuesday" << std::endl;
break;
case Day::Wednesday:
std::cout << "Wednesday" << std::endl;
break;
case Day::Thursday:
std::cout << "Thursday" << std::endl;
break;
case Day::Friday:
std::cout << "Friday" << std::endl;
break;
case Day::Saturday:
std::cout << "Saturday" << std::endl;
break;
case Day::Sunday:
std::cout << "Sunday" << std::endl;
break;
default:
std::cout << "Invalid day" << std::endl;
break;
}
}

// 不好的写法:复杂的case体
switch (option) {
case 1:
// 50行复杂代码
break;
case 2:
// 另50行复杂代码
break;
}

// 好的写法:将复杂逻辑提取为函数
void handleOption1() {
// 50行复杂代码
}

void handleOption2() {
// 另50行复杂代码
}

switch (option) {
case 1:
handleOption1();
break;
case 2:
handleOption2();
break;
default:
handleInvalidOption();
break;
}

// 好的写法:使用枚举提高类型安全性
enum class Operation {
Add, Subtract, Multiply, Divide
};

double calculate(Operation op, double a, double b) {
switch (op) {
case Operation::Add:
return a + b;
case Operation::Subtract:
return a - b;
case Operation::Multiply:
return a * b;
case Operation::Divide:
return (b != 0) ? (a / b) : 0.0;
default:
return 0.0;
}
}

5. 现代C++中的分支语句优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// C++17:使用if语句的初始化语句
if (auto user = getUser(); user.isValid()) {
// 使用user
} else {
// 处理无效用户
}

// C++17:使用switch语句的初始化语句
switch (auto value = getValue(); value) {
case 1:
// 处理1
break;
case 2:
// 处理2
break;
default:
// 处理其他情况
break;
}

// C++17:使用结构化绑定和if语句
if (auto [x, y] = getCoordinates(); x > 0 && y > 0) {
// 处理第一象限的点
}

// C++20:使用概念约束的模板分支
template <typename T>
void process(T value) {
if constexpr (std::integral<T>) {
// 处理整数类型
} else if constexpr (std::floating_point<T>) {
// 处理浮点类型
} else if constexpr (std::ranges::range<T>) {
// 处理范围类型
} else {
// 处理其他类型
}
}

常见错误和陷阱

1. 赋值运算符与相等运算符混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 错误:使用赋值运算符而不是相等运算符
if (x = 5) { // 总是为真,因为x被赋值为5
std::cout << "x is 5" << std::endl;
}

// 正确:使用相等运算符
if (x == 5) {
std::cout << "x is 5" << std::endl;
}

// 如何避免:使用常量在左侧(如果可能)
// 这样如果误用赋值运算符,会导致编译错误
if (5 == x) { // 更安全的写法
std::cout << "x is 5" << std::endl;
}

// 实际案例:密码验证
// 错误写法
if (password = "secret") { // 总是为真
std::cout << "Access granted" << std::endl;
}

// 正确写法
if (password == "secret") {
std::cout << "Access granted" << std::endl;
}

2. 逻辑运算符与位运算符混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 错误:使用位运算符而不是逻辑运算符
if (a & b) { // 位与,不是逻辑与
std::cout << "Both a and b are non-zero" << std::endl;
}

// 正确:使用逻辑运算符
if (a && b) {
std::cout << "Both a and b are true" << std::endl;
}

// 区别:
// && 是逻辑与,只关心操作数的真假,有短路特性
// & 是位与,对操作数的每一位进行与操作,没有短路特性

// 实际案例:权限检查
// 错误:使用逻辑与检查权限位
if (userPermissions && READ_PERMISSION) { // 错误:逻辑与
// 即使userPermissions没有READ_PERMISSION,也可能为真
}

// 正确:使用位与检查权限位
if (userPermissions & READ_PERMISSION) { // 正确:位与
// 只有当userPermissions包含READ_PERMISSION时才为真
}

3. 连续比较错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 错误:连续比较
if (10 < x < 20) { // 实际计算:(10 < x) < 20
std::cout << "x is between 10 and 20" << std::endl;
}

// 正确:使用逻辑与
if (10 < x && x < 20) {
std::cout << "x is between 10 and 20" << std::endl;
}

// 连续比较的实际计算过程
int x = 25;
bool result = (10 < x < 20);
// 1. 计算 10 < x → true (值为1)
// 2. 计算 1 < 20 → true
// 所以result为true,即使25不在[10, 20]范围内

// 实际案例:年龄检查
// 错误写法
if (18 <= age <= 65) { // 错误的连续比较
std::cout << "Eligible for work" << std::endl;
}

// 正确写法
if (age >= 18 && age <= 65) {
std::cout << "Eligible for work" << std::endl;
}

4. 浮点数比较错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 错误:直接比较浮点数
if (x == 0.1) { // 浮点数有精度问题
std::cout << "x is exactly 0.1" << std::endl;
}

// 正确:使用容差比较
const double EPSILON = 1e-9;
if (std::abs(x - 0.1) < EPSILON) {
std::cout << "x is approximately 0.1" << std::endl;
}

// 浮点数精度问题的原因
// 0.1在二进制中是无限循环小数,无法精确表示
// 因此,0.1 + 0.2 != 0.3

// 实际案例:计算结果比较
// 错误写法
if (calculatePi() == 3.14159) { // 直接比较浮点数
std::cout << "Pi calculated correctly" << std::endl;
}

// 正确写法
if (std::abs(calculatePi() - 3.14159) < 1e-5) {
std::cout << "Pi calculated correctly" << std::endl;
}

5. 短路求值依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 错误:依赖短路求值的副作用
int i = 0;
if (i < 5 && (i++) < 10) {
// i会递增
}

// 如果修改为||,行为会改变
if (i < 5 || (i++) < 10) {
// i不会递增,因为i < 5为真
}

// 更危险的情况
int j = 0;
if (someCondition() && (j++) > 0) {
// j的递增依赖于someCondition()为真
}

// 如何避免:避免在逻辑表达式中使用有副作用的操作
int k = 0;
bool condition = someCondition();
k++;
if (condition && k > 0) {
// 副作用与逻辑判断分离
}

// 实际案例:文件读取
// 错误:依赖短路求值的副作用
std::ifstream file("data.txt");
std::string line;
if (file.is_open() && std::getline(file, line)) {
// 读取成功
}

// 虽然上面的代码看似合理,但如果逻辑复杂,可能会导致问题
// 更清晰的写法
std::ifstream file("data.txt");
if (file.is_open()) {
std::string line;
if (std::getline(file, line)) {
// 读取成功
}
}

6. 类型转换导致的比较错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 错误:有符号整数与无符号整数比较
int a = -1;
unsigned int b = 1;
if (a < b) { // 错误:a会被转换为无符号整数,变成很大的正数
std::cout << "a < b" << std::endl;
} else {
std::cout << "a >= b" << std::endl; // 会执行这里
}

// 正确:显式类型转换
if (static_cast<long long>(a) < static_cast<long long>(b)) {
std::cout << "a < b" << std::endl; // 会执行这里
}

// 实际案例:数组索引比较
// 错误写法
int index = -1;
unsigned int size = 10;
if (index < size) { // 错误:index被转换为无符号整数
// 可能导致数组越界
}

// 正确写法
if (index >= 0 && static_cast<unsigned int>(index) < size) {
// 安全的索引检查
}

7. 空指针解引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 错误:未检查空指针
if (ptr->value > 0) { // 如果ptr为nullptr,会导致未定义行为
// ...
}

// 正确:先检查空指针
if (ptr != nullptr && ptr->value > 0) {
// ...
}

// 更简洁的写法(C++11+)
if (ptr && ptr->value > 0) {
// ...
}

// 实际案例:配置读取
// 错误写法
if (config->timeout > 0) { // 如果config为nullptr,会崩溃
// 设置超时
}

// 正确写法
if (config && config->timeout > 0) {
// 设置超时
}

小结

本章深入探讨了C++中的分支语句和逻辑运算符,从基础概念到高级应用,全面展示了专家级的编程技巧和最佳实践:

核心内容总结

  1. 分支语句的专业应用

    • if语句的初始化语句(C++17+)和if constexpr(C++17+)的编译时分支
    • switch语句的初始化语句、枚举类型集成以及C++26的模式匹配预览
    • 早期返回、函数提取等避免深度嵌套的高级技巧
  2. 逻辑运算符的深度解析

    • 短路求值的原理、应用场景和潜在陷阱
    • 逻辑表达式的性能优化策略,包括条件顺序调整和计算结果缓存
    • 位运算在特定场景下的性能优势
  3. 关系运算符的专业实践

    • 三路比较运算符(C++20+)的使用和比较类别的理解
    • 默认比较(C++20+)的最佳实践
    • 整数、浮点数和指针比较的安全性考虑
  4. 条件运算符的高级技巧

    • 与lambda表达式、智能指针和现代C++类型的集成
    • 性能优化和可读性平衡的专业判断
  5. 现代C++特性的融合

    • std::optional、std::variant等现代类型在分支逻辑中的应用
    • 概念(C++20+)和协程(C++20+)中的条件判断
    • 范围库(C++20+)中的逻辑表达式
  6. 专家级最佳实践

    • 代码可读性的专业标准,包括缩进、空格、注释和大括号使用
    • 复杂条件的函数提取和命名技巧
    • 枚举类型、命名常量和布尔变量的专业应用
  7. 常见错误的专业规避

    • 赋值运算符与相等运算符混淆的防范措施
    • 逻辑运算符与位运算符的正确区分
    • 连续比较、浮点数比较和类型转换导致的陷阱规避

专业编程洞见

分支语句和逻辑运算符是C++程序控制流程的核心组成部分,它们的使用水平直接反映了编程者的专业素养。专家级程序员不仅能够正确使用这些语言特性,还能在性能、可读性和可维护性之间找到最佳平衡。

现代C++提供了丰富的工具和特性,如if语句的初始化语句、三路比较运算符、概念等,这些特性使得分支逻辑的表达更加简洁、安全和高效。掌握这些现代特性,并将其与传统技巧有机结合,是成为C++专家的必经之路。

在实际编程中,应始终遵循以下专业原则:

  • 清晰性优先:优先考虑代码的可读性和可维护性,避免过度追求技巧性
  • 安全性至上:注意空指针检查、类型转换和边界条件,避免未定义行为
  • 性能意识:在关键路径上优化条件判断和逻辑表达式,合理利用短路求值
  • 现代特性:积极采用现代C++特性,提升代码质量和开发效率

通过合理运用本章介绍的知识和技巧,您可以编写出更加专业、高效、可靠的C++代码,展现出专家级的编程水准。在后续章节中,我们将这些分支逻辑技巧与循环语句、数组、指针等更高级的C++特性相结合,构建更加复杂和强大的程序。