1 C++基础
1.1 语句和程序结构
- 语句是一条让计算机执行某个动作的指令,是C++语言中最小的
独立计算单元
在高级语言(例如C++)中,一条语句可能编译成多条机器指令
- 大多数语句以
;
结尾
声明语句
跳转
表达式语句
复合语句
选择语句(条件语句)
迭代语句(循环语句)
try代码块
- 函数是顺序执行的语句的集合
- 每个C++程序都
必须有一个main函数
。当程序运行时,main函数中的语句按顺序执行 - 在编程中,函数/对象/类型/模板的名字称为
标识符
- 编译器负责检查代码是否符合C++语言的基本语法,如果不符合就会报语法错误
1.2 注释
- 注释会被编译器忽略
- 在库、程序或函数级别,使用注释来描述这些代码要实现的功能(
what
) - 在库、程序或函数中,使用注释来描述如何实现(
how
) - 在语句级别,使用注释来描述原因(
why
)
1.3 对象和变量介绍
程序就是指令的集合,这些指令会操纵数据以产生需要的结果
,数据是任何可以由计算机移动、处理或存储的信息。- 数据在计算机中是以二进制形式存储的
- 当运行程序时,操作系统会将程序加载到RAM中。任何硬编码到程序本身的数据(例如"hello,world"等文本)也会在这时候被加载
操作系统还会保留一些额外的RAM,供程序在运行时使用。此内存的常见用途是存储用户的输入/存储文件或网络中读取的数据/存储程序运行时计算得到的值,以便后续使用
可以将RAM看作一系列编号的方格,可用于在程序运行时存储数据
- 一个对象是一块可以存储值的内存区域
可以使用对象来存储和获取值,不用知道这些对象实际存放在内存中的哪个位置
- 可以用一个标识符来命名一个对象,
带有名字的对象称为变量
实例化
代表对象将被创建并分配一个内存地址,变量在使用之前必须被实例化
- 在C++中,
变量的类型在编译期就确定
了,并且不能被改变
1.4 变量赋值和初始化
- 使用=进行变量赋值的方式叫做拷贝赋值:将=右边的值拷贝到=左边的变量中
- 不同形式的初始化
int a; // 默认初始化
int b = 5; // 拷贝初始化
int c(6); // 直接初始化
// 列表初始化方法(c++11,更推荐)
int d{7}; // 直接列表初始化
int e = {8}; // 拷贝列表初始化
int f{}; // 值初始化
- 在大多数情况下,默认初始化不执行任何初始化,因此变量具有不确定的值
- 对于复杂类型来说,拷贝初始化的效率较低(c++17中修复了这些问题)
- 当值被隐式地复制或转换时,也会使用拷贝初始化。例如通过值将参数传递给函数、通过值从函数返回、通过值捕获异常
- 直接初始化最初是为了更有效地初始化复杂对象而引入的;当值被显式地转换为另一种类型时,可以使用直接初始化
- 使用列表初始化时,编译器会检查类型是否匹配
int a = 4.5; // 编译通过
int b(4.5); // 编译通过
int c{4.5}; // 编译报错
- {}会将变量初始化为0或空,因此值初始化也称零初始化
[[maybe_unused]]
可以用于修饰一些暂时不使用的变量,从而不会产生编译告警
1.5 iostream介绍
- io库是C++标准库的一部分,用于处理基本输入输出
- io库包含了一些预定义的变量供使用,例如
std::cout
和std::cin
<<
称为插入运算符,>>
称为提取运算符std::cout
会将输出内容先存入缓冲区std::endl
除了会输出一个新行,还会刷新缓冲区,因此效率不如\n
- C++的io库未提供一种方法,可以在用户不按回车键的情况下接收键盘输入(有些第三方库提供了这种方法)
- 输入缓冲区中的每行输入数据都以
\n
字符结束 - 基本的提取过程:
- 1.前置的空格、制表符、换行符都会被丢弃
- 2.如果输入缓冲区是空的,
>>
将等待用户输入 - 3.
>>
会提取尽可能多的连续字符,直到遇到换行符或者对于接收变量来说无效的字符
- 提取的结果:
- 如果上面的步骤3中提取了任何字符,则提取成功。提取的字符被转换成一个值并赋给变量
- 如果步骤3没有提取到任何字符,则提取失败。后面的所有提取都会立即失败,直到std::cin被清空
- 任何未提取的字符(包括换行符)仍可用于下一次提取尝试
int x{};
std::cin>>x;
如果用户输入了5a并回车,则5被赋给了x,a和\n则留在了输入缓冲区用于下一次提取
如果用户输入了b并回车,由于b不是有效的整数,因此提取失败,x被设置为0,未来的提取都会失败,直到输入流被清空
1.6 未初始化的变量和未定义的行为
- 一个未初始化的变量的默认值就是那个内存地址中本来就已经存在的值(是不确定的)
- 未定义的行为可能有如下表现:
- 程序每次运行产生不同结果
- 程序总是产生同样的错误结果
- 程序看起来在工作,但在之后又产生错误结果
- 程序崩溃
- 程序在一些编译器上工作,但在另一些编译器不工作
- 程序不工作,除非改变一些看似无关的代码
implementation-defined behavior
指的是留给实现(编译器)来定义的语法行为
,这些行为必须是一致的且有文档记录,不同的编译器可能会产生不同的结果
- 避免使用与编译器的具体实现相关的语法,例如sizeof