01 语句:依序执行的基础程序片段

  语句(statement)就是依序执行的基础程序片段。C++ 程序就是由一个或多个包含不同类型 语句 的文本文件序列所组成的。C++ 包含了以下类型的语句:

  • 表达式语句(expression statement)
  • 声明语句(declaration statement)
  • 选择语句(selection statement)
  • 循环语句(iteration statement)
  • 跳转语句(jump statement)
  • 复合语句(compound statement)

  每种语句都可以添加标签。
  除了这些语句以外还有用在特殊地方的 try 块和 atomic 与 synchronized 块。

标签

  可以为语句自身之前添加后随冒号的标签(label),任何语句都可带有标签。标签的语法结构有以下三种:


属性(可选) 标识符 : 语句 ;


属性(可选) case 常量表达式 : 语句 ;


属性(可选) default : 语句 ;


表达式语句

  C++ 程序的大部分语句都是表达式语句,例如赋值和函数调用。表达式的语法结构如下:


属性(可选) 表达式(可选) ;


  表达式 是由运算符和它们的操作数构成的序列,它指定了一项计算。表达式的内容非常丰富,会在其他地方再进行梳理。

// 两个示例
n = n + 1;                        
std::cout << "n = " << n << '\n'; 

  没有表达式的表达式语句被称作空语句(null statement)。它通常用来为 for 或 while 循环提供空体。它也可用于在复合语句的末尾引入标签。

声明语句

  声明语句用于将名字引入(或再引入)到 C++ 程序中。一般的简单声明语法结构如下:


属性(可选) 声明说明符序列 初始化声明符列表 ;


// 一个示例
class C
{
    std::string member; 
} obj, *pObj(&obj);
// 声明说明符序列是 "class C { std::string member; }"
// 声明符 "obj" 声明了一个类型为 C 的对象
// 声明符 "*pObj(&obj)" 声明了一个指向 C 的指针,并嵌套声明了一个返回该指针的函数对象。

  简单声明是引入、创建并可能会初始化一个或数个标识符(典型地为变量)的语句。除此以外,还有其他实体的不同声明方式。

选择语句

  选择语句用于在数个控制流中选择一个。按语法结构分,选择语句有 if 语句和 switch 语句两种,其中 if 语句根据带不带 else 分支以及是否为 consteval if 语句分为四种。语法结构如下:
  首先是 if 语句的语法结构:


属性(可选) if constexpr (可选) ( 初始化语句(可选) 条件 ) true分支语句


属性(可选) if constexpr (可选) ( 初始化语句(可选) 条件 ) true分支语句 else false分支语句


属性(可选) if ! (可选) consteval 复合语句


属性(可选) if ! (可选) consteval 复合语句 else 语句


  if 语句的 条件 可以是一个能按语境将类型转换为bool表达式 ,或者是一个非数组变量的带花括号或等号初始化器的 声明
  如果 条件 在转换到 bool 后产生 true,那么执行 true分支语句。如果 if 语句存在 else 部分,且 条件 在转换到 bool 后产生 false,那么执行 false分支语句。若 if 语句包含 else,如果 true分支语句 也是 if 语句,那么内层 if 语句必须也含有 else 部分(换言之,在嵌套 if 语句中 else 关联到最近的尚未有 else 的 if)。

// 一个示例
// 嵌套 if 语句
int j = 1;
if (i > 1)
    if (j > 2)
        std::cout << i << " > 1 且 " << j << " > 2\n";
    else // 此 else 属于 if (j > 2),而不是 if (i > 1)
        std::cout << i << " > 1 且 " << j << " <= 2\n";

  if 语句的 初始化语句 是一个 C++17 之后的特性,初始化语句 可以是一个表达式语句或一条简单声明。注意,如果使用了 初始化语句初始化语句 所声明的名字和 条件 所声明的名字以及两条 分支语句 处于同一个作用域中。
  constexpr 是一个 C++11 之后的关键词,但是 consteval if 语句是一个 C++17 后的特性。当该关键词出现时,该语句即为 constexpr if 语句。该语句可以帮助实现条件编译,即在编译期完成条件判断,并舍弃用不上的代码,且被舍弃的语句可以 ODR 使用未定义的变量。更详细的用法会单独整理。

  consteval 是一个 C++20 之后的关键词,但是 consteval if 语句是一个 C++23 后的特性,暂且略过。
  然后是 switch 语句的语法结构:


属性(可选) switch ( 初始化语句(可选) 条件 ) 语句


  switch 语句的 条件 可以是任何整型或枚举类型,或者是一个能按语境隐式转换到整型或枚举类型的表达式,也可以是一个非数组变量的带花括号或等号初始化器的 声明 ,且类型也必须是整型或枚举类型。
  switch 语句的 语句 可以使用 casedefault 标签,且 break 语句具有特殊含义。其语法结构为:


属性(可选) case 常量表达式 : 语句


属性(可选) default : 语句


  switch 语句可拥有任意数量的 case 标签,只要所有 常量表达式 的值在转换或提升后均为唯一。最多可以存在一个 default 标签,但是嵌套的 switch 语句可以使用其自身的 default 标签,或拥有和外部 switch 使用完全相同的常量的 case 标签。
  如果 条件 求值为等于 常量表达式 之一的值,那么控制流被转移到用该 常量表达式 标签标记的语句。如果 条件 求值为不匹配任何 case 标签的值,且存在 default 标签,那么控制流被转移到带有 default: 标号的语句。当 语句 中遇到 break 语句时退出 switch 语句:

// 三个示例
int i = 2;
switch (i) {
    case 1: std::cout << "1";
    case 2: std::cout << "2";   // 执行从这个标签开始
    case 3: std::cout << "3";
    case 4:
    case 5: std::cout << "45";
            break;              // 终止后继语句的执行
    case 6: std::cout << "6";
}

std::cout << '\n';

switch (i) {
        case 4: std::cout << "a";
        default: std::cout << "d"; // 没有适用的常量表达式
                                   // 因此执行 default
    }

// 当在 switch 语句中使用枚举时,如果有一个枚举项没有处理,许多编译器都会发布警告
enum color {RED, GREEN, BLUE};
switch(RED) {
    case RED:   std::cout << "红\n"; break;
    case GREEN: std::cout << "绿\n"; break;
    case BLUE:  std::cout << "蓝\n"; break;
}    

  switch 语句的 初始化语句 和 if 语句的用法相同。

循环语句

  循环语句用于重复执行一些代码。


属性(可选) while ( 条件 ) 循环语句


  while 循环的 条件 可以是一个能按语境转换为 bool 的任意表达式,或者是一个非数组变量的带花括号或等号初始化器的 声明
  while 循环的 循环语句 可以是任意语句,一般为复合语句。
  while 循环将重复执行 循环语句,直到 条件 的值变成 false,且每次重复之前都会进行检测。

//三个例子
// 带单语句的 while 循环
int i = 0;
while (i < 10)
     i++;
std::cout << i << '\n';
// 带复合语句的 while 循环
int j = 2;
while (j < 9) {
    std::cout << j << ' ';
    j += 2;
}
std::cout << '\n';

// 带声明条件的 while 循环
char cstr[] = "Hello";
int k = 0;
while (char c = cstr[k++])
    std::cout << c;
std::cout << '\n';

  如果循环的执行必须在某点终止,那么可以使用 break 语句作为终止语句。
  如果循环需要在循环体结尾继续,那么可以使用 continue 语句作为快捷方式。


属性(可选) do 循环语句 while ( 表达式 ) ;


  do-while 循环的 循环语句 可以是任意语句,一般为复合语句。
  do-while 循环的 表达式 可以是一个能按语境转换为 bool 的任意表达式。
  do-while 循环将重复执行 循环语句,直到 表达式 的值变成 false,且每次重复之后进行检测,这里与 while 循环不同,也就是说,do-while 循环将始终至少执行一次 循环语句,即使 表达式 始终产生 false

//一个例子
int j = 2;
do { // 循环体是复合语句
    j += 2;
    std::cout << j << " ";
} while (j < 9);

  如果循环的执行必须在某点终止,那么可以使用 break 语句作为终止语句。
  如果循环需要在循环体结尾继续,那么可以使用 continue 语句作为快捷方式。


属性(可选) for ( 初始化语句(可选) 条件 ; 表达式(可选) ) 循环语句


  for 循环的 条件 可以是一个能按语境转换为 bool 的任意表达式,或者是一个非数组变量的带花括号或等号初始化器的 声明 。注意,空的 条件 等价于 while(true)
  for 循环的 表达式 可以是任意表达式,通常是增加循环计数器的表达式。注意,语句 中的 continue 语句将执行一次表达式
  for 循环的 初始化语句 可以是一个表达式语句或一条简单声明。注意,如果使用了 初始化语句初始化语句 所声明的名字和 条件 所声明的名字处于同一个作用域中。
  for 循环的 循环语句 可以是任意语句,一般为复合语句。
  for 循环将执行一次 初始化语句,然后重复执行 循环语句表达式,直到 条件 的值变成 false,且每次迭代前都进行该检测。

//几个例子
// 典型的以单语句作为循环体的循环
for (int i = 0; i < 10; ++i)
    std::cout << i << ' ';
std::cout << '\n';

// 初始化语句可以声明多个名字,
// 只要它们可以使用相同的声明说明符序列
for (int i = 0, *p = &i; i < 9; i += 2) {
    std::cout << i << ':' << *p << ' ';
}
std::cout << '\n';

// (循环)条件可以是声明
char cstr[] = "Hello";
for (int n = 0; char c = cstr[n]; ++n)
    std::cout << c;
std::cout << '\n';

// 初始化语句可以使用 auto 类型说明符
std::vector<int> v = {3, 1, 4, 1, 5, 9};
for (auto iter = v.begin(); iter != v.end(); ++iter){
    std::cout << *iter << ' ';
}
std::cout << '\n';
 
// 初始化语句可以是表达式
int n = 0;
for (std::cout << "循环开始\n";
     std::cout << "循环测试\n";
     std::cout << "迭代 " << ++n << '\n')
    if(n > 1)
        break;
std::cout << '\n';

属性(可选) for ( 初始化语句(可选) 范围变量声明 : 范围表达式 ) 循环语句


  基于范围的 for 循环是一个 C++11 后的特性,用作对范围中的各个值(如容器中的所有元素)进行操作的相对传统 for 循环来说更加可读的等价版本。
  基于范围的 for 循环与 for 循环的 初始化语句 没有什么不同,但是是一个 C++20 后的特性。
  基于范围的 for 循环的 范围变量声明 是一个命名变量的声明。该变量的类型应是由 范围表达式 所表示的序列的元素的类型,或该类型的应用。
  基于范围的 for 循环的 循环语句 可以是任意语句,一般为复合语句。
  基于范围的 for 循环的 范围表达式 可以是表示了一个合适序列的表达式,或一个花括号初始化器列表。

//几个例子
std::vector<int> v = {0, 1, 2, 3, 4, 5};

for (const int& i : v) // 以 const 引用访问
    std::cout << i << ' ';
std::cout << '\n';

for (auto i : v) // 以值访问,i 的类型是 int
    std::cout << i << ' ';
std::cout << '\n';

for (auto&& i : v) // 以转发引用访问,i 的类型是 int&
    std::cout << i << ' ';
std::cout << '\n';

const auto& cv = v;

for (auto&& i : cv) // 以转发引用访问,i 的类型是 const int&
    std::cout << i << ' ';
std::cout << '\n';

for (int n : {0, 1, 2, 3, 4, 5}) // 初始化器可以是花括号初始化器列表
    std::cout << n << ' ';
std::cout << '\n';

int a[] = {0, 1, 2, 3, 4, 5};
for (int n : a) // 初始化器可以是数组
    std::cout << n << ' ';
std::cout << '\n';

for ([[maybe_unused]] int n : a)  
    std::cout << 1 << ' '; // 不必使用循环变量
std::cout << '\n';

for (auto n = v.size(); auto i : v) // 初始化语句(C++20)
    std::cout << --n + i << ' ';
std::cout << '\n';

for (typedef decltype(v)::value_type elem_t; elem_t i : v)
// typedef 声明作为初始化语句(C++20)
    std::cout << i << ' ';
std::cout << '\n';

for (using elem_t = decltype(v)::value_type; elem_t i : v)
// 别名声明作为初始化语句,同上(C++23)
    std::cout << i << ' ';
std::cout << '\n';

跳转语句

  跳转语句用于转移控制流。


属性(可选) break ;


  break 语句将导致外围的 for、范围 for、while 或 do-while 循环或 switch 语句终止。


属性(可选) continue 表达式(可选) ;


  continue 语句导致外围 for、范围 for、while 或 do-while 循环的剩余部分被跳过。


属性(可选) return 表达式(可选) ;


属性(可选) return 花括号初始化器列表 ;


  return 语句的表达式是一个能转换到函数返回类型的表达式。
  return 语句会终止当前函数并返回指定值(如果存在)给调用方函数。


属性(可选) goto 标识符 ;


  goto 语句用于无条件转移控制流,需要与标签结合使用。

参考

C++ 参考手册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值