1. 语句基础
● 语句的常见类别
– 表达式语句:表达式后加分号,对表达式求值后丢弃,可能产生副作用
– 空语句:仅包含一个分号的语句,可能与循环一起工作
– 复合语句(语句体):由大括号组成,无需在结尾加分号,形成独立的域(语句域)
分号:标志语句的结束
顺序语句与非顺序语句
– 顺序语句
● 从语义上按照先后顺序执行
● 实际的执行顺序可能产生变化(编译器优化、硬件乱序执行)
● 与硬件流水线紧密结合,执行效率较高
– 非顺序语句:选择 | 循环 | goto
● 在执行过程中引入跳转,从而产生复杂的变化
● 分支预测错误可能导致执行性能降低
● 最基本的非顺序语句: goto
– 通过标签指定跳转到的位置
– 具有若干限制
● 不能跨函数跳转
● 向前跳转时不能越过对象初始化语句
– 向后跳转可能会导致对象销毁与重新初始化
● goto 本质上对应了汇编语言中的跳转指令
– 缺乏结构性的含义
– 容易造成逻辑混乱
– 除特殊情况外,应避免使用,非必要 不要写这种shit!
2. 分支语句
1、if else: 语法
● 使用语句块表示复杂的分支逻辑
● 从 if 到 if-else
– 实现多重分支
– else 会与最近的 if 匹配
– 使用大括号改变匹配规则,没有大括号只执行下一行
● if V.S. constexpr if—— 运行期与编译期分支
● 带初始化语句的 if:c++ 17以后
2、switch{}: 语法
● 条件部分应当能够隐式转换为整形或枚举类型,可以包含初始化的语句
C++17:
● case/default 标签
– case 后面跟常量表达式 , 用于匹配 switch 中的条件,匹配时执行后续的代码
– 可以使用 break 跳出当前的 switch 执行,记得break,一般每一个分支都加,最后一个也加
– default 用于定义缺省情况下的逻辑
– 在 case/default 中定义对象要加大括号 { },
●[[fallthrough]] 属性:代替break,但是不跳出
● 与 if 相比的优劣
– 分支描述能力较弱,需要列举
– 在一些情况下能引入更好的优化
3. 循环语句
A、while() : 语法
● 处理逻辑:
– 1. 判断条件是否满足,如果不满足则跳出循环
– 2. 如果条件满足则执行循环体
– 3. 执行完循环体后转向步骤 1
● 注意:
在 while 的条件部分不包含额外的初始化内容
while();是一个死循环
B、do-while: 语法
– 注意结尾处要有分号,表示一条语句的结束
● 处理逻辑:
– 1. 执行循环体
– 2. 断条件是否满足,如果不满足则跳出循环
– 3. 如果条件满足则转向步骤 1
C、for: 语法
for ( int v:arr) {
cout<<v<<endl;
}
● 处理逻辑
– 1. 初始化语句会被首先执行
– 2. 条件部分会被执行,执行结果如果为 false ,则终止循环
– 3. 否则执行循环体
– 4. 迭代表达式会被求值,之后转向 2
● 在初始化语句中声明多个名字
● 初始化语句、条件、迭代表达式可以为空
● for 的更多示例
D、基于范围的 for 循环: 语法:
● 本质:语法糖,编译器会转换为 for 循环的调用方式
● 转换形式的衍化: C++11 / C++17 / C++20
● 使用常量左值引用读元素;使用 万能引用( “ universal reference )”修改元素
4. 语句的综合应用——达夫设备
● 使用循环展开提升系统性能
● 处理无法整除的情形
– 额外增加一个循环语句
– 将 switch 与循环结合 —— 达夫设备
课件讲的没听懂,以下from chatgpt:
在C++中,“达夫设备”(Duff’s device)是一种优化技术,用于加速循环的执行。它是由程序员Tom Duff在1983年提出的,并被广泛使用于C语言和C++中。
达夫设备的主要思想是利用了C语言的"跳跃表达式"(jump table)和"case"语句的结合来实现循环的并行执行。这种技术主要用于在处理大量数据的情况下提高程序的执行效率。
达夫设备的一般实现方式如下:
unsigned count = N;
unsigned n = (count + 7) / 8;
switch (count % 8) {
case 0: do {
// 处理循环体语句
} while (--n > 0);
case 7: do {
// 处理循环体语句
} while (--n > 0);
case 6: do {
// 处理循环体语句
} while (--n > 0);
case 5: do {
// 处理循环体语句
} while (--n > 0);
case 4: do {
// 处理循环体语句
} while (--n > 0);
case 3: do {
// 处理循环体语句
} while (--n > 0);
case 2: do {
// 处理循环体语句
} while (--n > 0);
case 1: do {
// 处理循环体语句
} while (--n > 0);
}
这段代码使用了一个switch语句来检查循环次数的余数(count % 8),然后根据不同的余数执行不同的循环体语句,直到计数器n减少为0。通过这种方式,可以实现循环的并行执行,提高程序的效率。
需要注意的是,达夫设备是一种特定的优化技术,使用时需要谨慎。在现代编译器中,通常会进行更复杂的优化,因此达夫设备可能并不总是比编译器生成的代码更高效。此外,达夫设备的使用也可能降低代码的可读性和可维护性,因此在实际开发中应权衡利弊并慎重选择是否使用。