简单语句
空语句
如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会用到空语句。
复合语句
复合语句( compoundstatement)是指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称作块( block) 。一个块就是一个作用域 :::info 块不会以分号作为结束 :::
语句作用域
可以在if
、switch
、while
和for
语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了
条件语句
else
与离它最近的尚未匹配的if
匹配
这个问题通常称作悬垂else,在那些既有if
语句又有if else
语句的编程语言中是个普遍存在的问题。不同语言解决该问题的思路也不同,就C++ 而言,它规定else
与离它最近的尚未匹配的if
匹配,从而消除了程序的二义性。- 要想使
else
分支和外层的江语句匹配起来,可以在内层if
语句的两端加上花括号,使其成为一个块Switch语句
理解程序在case标签之间的执行流程非常重要。如果某个case标签匹配成功,将从该标签开始往后顺序执行所有case分支,除非程序显式地中断了这一过程,否则直到switch的结尾处才会停下来。要想避免执行后续case分支的代码,我们必须显式地告诉编译器终止执行过程。大多数情况下,在下一个case
标签之前应该有一条break
语句。default标签
即使不准备在default标签下做任何工作,定义一个default标签也是有用的。其目的在于告诉程序的读者,我们已经考虑到了默认的情况,只是目前什么也没做。switch内部的变量定义
如前所述,switch的执行流程有可能会跨过某些case标签。如果程序跳转到了某个特定的case ,则switch结构中该case标签之前的部分会被忽略掉。这种忽略掉一部分代码的行为引出了一个有趣的问题: :::danger 如果被略过的代码中含有变量的定义该怎么办? ::: 答案是:如果在某处一个带有初值的变量位于作用域之外,在另一处该变量位于作用域之内,则从前一处跳转到后一处的行为是非法行为
迭代语句
迭代语句通常称为循环,它重复执行操作直到满足某个条件才停下来。while
和for
语句在执行循环体之前检查条件,do-while
语句先执行循环体,然后再检查条件。
:::tips
定义在while内或是循环体内的变量,每次循环都经过创建再销毁的过程
:::
for语句头中的多重定义
和其他的声明一样,init-statement 也可以定义多个对象。但是init-statement只能有一条声明语句,因此,所有变量的基础类型必须相同
for语句头能省略掉init-statement、 condition和expression中的任何一个( 或者全部 )。 如果无须初始化,则我们可以使用一条空语句作为init-statement。
范围for语句
C++11新标准引入了一种更简单的for语句,这种语句可以遍历容器或其他序列的所有元素。
for(declaration:expresssion)
statement;
declaration
定义一个变量,序列中的每个元素都得能转换成该变量的类型。确保类型相容最简单的办法是使用auto类型说明符,这个关键字可以令编译器帮助我们指定合适的类型。如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型。
范围for语句的原理
for(auto beg=v.begin(),end=v.end();beg!=end;++beg){//实际上是通过迭代器得到了序列的起止点
auto &r=*beg;
r*=2;
}
:::danger
不能通过范围for语句增加vector对象(或者其他容器)的元素了。在范围for语句中, 预存了end()
的值。一旦在序列中添加(删除)元素,end
函数的值就可能变得无效了.
:::
跳转语句
跳转语句中断当前的执行过程。C++语言提供了4 种跳转语句:break
、continue
、goto
和return
。
break语句
break
语句负责终止离它最近的while、dowhile、for 或switch语句,并从这些语句之后的第一条语句开始继续执行。
continue语句
continue
语句终止最近的循环中的当前迭代并立即开始下一次迭代。continue语句只能出现在for、while和do-while 循环的内部,或者嵌套在此类循环里的语句或块的内部。
:::danger
不要在程序中使用goto
语句,因为它使得程序既难理解又难修改。
:::
try语句块异常处理
异常
- 异常是指存在运行时的反常行为,这些行为超出了函数正常功能的范围。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。
throw
表达式:异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。try
语句块,异常处理部分使用try
语句块处理异常。try语句块以关键字七try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句“处理” 异常,所以它们也被称作异常处理代码(exception hander)。- 一套异常类(exception class) ,用于在throw表达式和相关的catch子句之间传递异常的具体信息。
throw表达式
程序的异常检测部分使用throw表达式引发一个异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw表达式后面通常紧跟一个分号,从而构成一条表达式语句。
if(xxx)
throw runtime_error("Data error");
try语句块
try{
program
}catch(exception declaration){
hander-statement;
}catch(exception declaration){
hander-statement;
}
catch子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明), 以及一个块。当选中了某个catch处理异常之后,执行与之对应的块。catch一但完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。
多个try语句
于找处理代码的过程与函数调用链刚好相反。当异常被抛出时。首先搜索抛出该异常的函数。如果没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。