前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《C++Primer》第五章 语句

《C++Primer》第五章 语句

作者头像
TOMOCAT
发布2020-12-02 11:54:54
9730
发布2020-12-02 11:54:54
举报

写这篇文章的目的

身为C++的零基础初学者,短期内把《C++Primer》啃下来是一个比较笨但是有效的方法,一方面可以掌握比较规范的C++语法(避免被项目中乱七八糟的风格带跑偏),另一方面又可以全面地了解C++语法以及C++11新标准(后续要做的事情就剩下查漏补缺,不断完善自己的知识体系)。

个人感觉从零学习一门新知识比较好的方法是快速了解知识的全貌,然后构建自己的知识地图,后续不断地补充相应的细节。

由于《C++Primer》和大多数的教科书一样废话连篇,因此想要精炼一下每篇文章的内容再打印成pdf,方便温故知新。

空语句

如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会使用到空语句。例如我们想读取输入流的内容直到遇到一个特定的值位置,除此之外什么事情都不做:

代码语言:javascript
复制
// 重复读入数据直至达到文件末尾或者某次输入的值等于sought
while (cin >> s && s != sought)
    ; // 空语句

if或者while条件后面跟了一个额外的空语句可能表示循环体是空的,可能引发错误。

语句作用域

可以在ifswitchwhilefor语句的控制结构内定义变量。定义在控制结构中的变量只在相应语句的内部内可见,一旦语句结束,变量也就超出其作用范围了。

如果其他代码也需要控制访问变量,则变量必须定义在语句的外部。

条件语句

1. if语句
  • 复杂if语句或者嵌套if语句时注意使用花括号,否则可能结果会超乎你的预期
  • 悬垂else:当一个if语句嵌套在另一个if语句内部时,很可能if语句会多于else语句,C++对于判断某个给定的else是与if匹配提供了方法:它规定else与离它最近的尚未分配的if匹配,从而消除了程序的二义性。
  • 如果希望else分支和最外层的if语句匹配起来,那么可以在内层if语句的两端加上花括号,使其成为一个块。
2. switch语句
  • case标签必须是整型常量表达式
  • 任何两个case标签的值不能相同,否则会引发错误
  • 如果某个case标签匹配成功,那么将从该标签开始往后顺序执行所有的case分支
  • 一般不要省略case分支最后的break语句,如果没写的话最好加上注释表示这样写的逻辑
  • 如果switch结构以一个空的default标签作为结束,则该default标签后面必须跟上一条空语句或者一个空块

循环语句

1. while语句
代码语言:javascript
复制
while (condition)
    statement
  • 定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程
  • 当不确定需要迭代多少次时,使用while循环比较合适
  • 还有一种情况也适合使用while循环:当我们想在循环结束后访问循环控制变量
2. 传统的for语句
代码语言:javascript
复制
for (init-statement; contidition; expression)
    statement
  • 牢记for语句中定义的对象只在for循环体内可见,这也是当我们想在循环结束后访问循环控制变量最好使用while的原因
  • init-statement可以定义多个对象,但是只能有一条声明语句,因此所有变量的基础类型必须相同
3. 范围for语句

C++11新标准引入了一种更加简单的for语句,用于遍历容器或者其他序列的所有元素:

代码语言:javascript
复制
for (declaration : expression)
    statement
  • expression表示的必须是一个序列,比如用花括号括起来的初始值列表、数组、vector或者string等类型的对象,这些对象的共同特点是可以返回迭代器的beginend成员
  • declaration定义一个变量,序列中的每个元素都能转换成该变量的类型,确保类型相容最简单的方法是使用auto类型说明符。如果需要对序列中的元素执行写操作,循环变量必须声明为引用类型
  • 不能通过范围for语句增加vector对象或者其他容器的元素,因为在范围for语句中预存了end()的值,一旦在序列中添加或者删除元素就会导致end函数的值变得无效

do while语句

do while语句和while语句基本一致,唯一的区别在于不管条件的值如何,do while都会至少执行一次循环:

代码语言:javascript
复制
do
    statement
while (condition);

跳转语句

1. break语句

break语句只能出现在迭代语句或者switch语句内部,负责终止离它最近的whiledo whileforswitch语句。

2. continue语句

continue终止最近的循环中的当前迭代并立即开始下一次迭代。

  • continue只能出现在forwhiledo while循环的内部
  • 仅作用于离它最近的循环
3. goto语句

goto语句的作用是从goto语句无条件跳转到同一函数内的另一条语句,不推荐在程序中使用goto语句,因为它使得程序又难理解又难修改

try语句和异常处理

异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持,在C++语言中异常处理包括:

  • throw表达式:异常检测部分使用thrrow表达式来表示它遇到了无法处理的问题,我们说throw引发raise了异常
  • try语句块:try以关键字try开始,并以一个或者多个catch子句结束。try语句块中抛出的异常通常会被某个catch子句处理,它们也被称为异常处理代码
  • 异常类:用于在throw表达式和相关的catch子句之间传递异常的具体信息
1. throw表达式

举个例子,下面的程序把两个Sales_item对象相加,检查读入的记录是否是关于同一种书籍的,如果不是就输出一条信息然后退出:

代码语言:javascript
复制
// 检查两条数据是不是关于同一种书籍的
if (item1.isbn() != item2.isbn())
    throw runtime_error("Data must refer to same ISBN");
cout << item1 + item2 << endl;

上述例子抛出了一个runtime_error的对象,该异常会终止当前函数,并将控制权交给能处理该异常的代码

2. try语句块
代码语言:javascript
复制
try {
    program-statements
} catch (exception-declaration) {
    handler-statements
} catch (exception-declaration) {
    handler-statements
}
  • try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问
  • 可通过runtime_error的成员函数what获取const char*C风格字符串
  • 如果一段程序没有try语句且发生了异常,那么系统会调用terminate函数并终止当前程序的运行
  • 对于需要处理异常并继续执行的程序,我们必须时刻清楚异常何时发生,异常发生后程序应如何确保对象有效、资源无泄漏和程序有无处于合理状态等
3. 标准异常

<stdexcept>定义的异常类:

代码语言:javascript
复制
exception             最常见的问题
runtime_error         只有在运行时才能检测出来的问题
range_error           运行时错误:生成的结果超出了有意义的值域范围
overflow_error        运行时错误:计算上溢
underflow_error       运行时错误:计算下溢
logic_error           程序逻辑错误
domain_error          逻辑错误:参数对应的结果值不存在
invalid_argument      逻辑错误:无效参数
length_error          逻辑错误:试图创建一个超出该类型最大长度的对象
out_of_range          逻辑错误:使用一个超出有效范围的值
  • 我们只能以默认初始化的方式初始化exceptionbad_allocbad_cast对象,不允许为这些对象提供初始值
  • 其他异常类型的行为恰恰相反,我们应该用string或者C风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值含有错误相关的信息。
  • 异常类型只定义了一个名为what的成员函数,返回值是一个指向C风格字符串的const char*,用于提供关于异常的一些文本信息。
  • 如果异常对象类型有一个字符串初始值,那么what会返回该值,对于其他无初始值的异常类型来说,what返回的内容由编译器决定
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写这篇文章的目的
  • 空语句
  • 语句作用域
  • 条件语句
    • 1. if语句
      • 2. switch语句
      • 循环语句
        • 1. while语句
          • 2. 传统的for语句
            • 3. 范围for语句
            • do while语句
            • 跳转语句
              • 1. break语句
                • 2. continue语句
                  • 3. goto语句
                  • try语句和异常处理
                    • 1. throw表达式
                      • 2. try语句块
                        • 3. 标准异常
                        相关产品与服务
                        容器服务
                        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档