环境搭建以及《C++ Primer》第一、二章
1. 环境搭建
参考网址:
https://www.cnblogs.com/cpuimage/p/13121765.html
(1) 下载msys2
https://www.msys2.org/
(2) 打开msys2控制台,输入以下命令进行环境安装
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-gdb
pacman -S mingw-w64-x86_64-cmake
pacman -S mingw-w64-x86_64-make
pacman -S mingw-w64-x86_64-pkg-config
(3) 下载并打开 CLion,进入setting中的Toolchains;点击 [+] 新建MinGW环境并配置,如下图

2. C++基础
(1) 相关术语
- 形参:
parameter,formal argument - 实参:
argument, actual argument - 编译器:
gcc(GUN Compiler Collection), 预处理、编译、汇编、链接 - 编辑器:
- 集成开发环境:
IDE(Integrated Developed Environment) - 语句块:
block,花括号包围的语句序列
(2) 向流写入数据
#include <iostream>
std::count << "Enter two numbers:" << std::endl;
std::cin >> v1 >> v2; // 从std::cin中读入两个值,第一个存入v1,第二个存入v2
endl操纵符(manipulator),结束当前行,并将缓冲区(buffer)中的内容刷到设备中;std命名空间(namespace)::作用域运算符//单行注释/* * */注释界定符
(3) 以 istream 对象作为条件的循环
#include <iostream>
int main() {
int sum = 0, value = 0;
while (std::cin >> value)
sum += value;
std::cout << "Sum is: " << std::endl;
return 0;
}
- 如果输入的流是有效的(在该代码中为
int型参数),则检测成功,条件为True; - 如果输入的流是无效的(除
int型参数外其他类型参数),则检测失败,条件为False,跳出循环。
3. 变量和基本类型
(1) 算术类型
| 类型 | 含义 | 最小尺寸 |
|---|---|---|
bool | 布尔类型 | 未定义 |
char | 字符 | 8 位 |
wchar_t | 宽字符 | 16 位 |
char16_t | Unicode 字符 | 16 位 |
char32_t | Unicode 字符 | 32 位 |
short | 短整型 | 16 位 |
int | 整形 | 16 位 |
long | 长整型 | 32 位 |
long long | 长整型 | 64 位 |
float | 单精度浮点数 | 6 位有效数字 |
double | 双精度浮点数 | 10 位有效数字 |
long double | 扩展精度浮点数 | 10 位有效数字 |
- 字节:8 比特
- 字: 32 或 64 比特
float一个字(32 比特)
(2) 类型转换
-
把非布尔类型的算术值赋给布尔类型时,初始值为0则结果为false,否则结果为true;
-
把浮点数赋给整数类型时,结果仅保留小数点前的部分;
-
表达式中既有负数又有无符号数时,会出现异常结果
(3) 字面值常量
-
以
0开头的整数代表八进制,以0x或0X开头的代表十六进制数,例如,可以用以下几种形式表示20:20 // 十进制024 // 八进制0x14 // 十六进制 -
单引号括起来的一个字符成为
char型字面值;双引号括起来的成为字符串型字面值,其结尾位为'\0' -
一个字符串字面值可以被空格、缩进、换行符分隔
std::cout << "a really, really long string literal " "that spans two lines" << std::endl; -
转义序列
escape sequence符号名称 符号表示 符号名称 符号表示 符号名称 符号表示 换行符 \n横向制表符 \t报警(响铃)符 \a纵向制表符 \v退格符 \b双引号 \"反斜线 \\问号 \?单引号 \'回车符 \r进纸符 \f -
\7响铃\12换行\40空格\0空字\115字符M\x4d字符M (\后面为八进制或者十六进制)
(4) 变量
-
初始化创建变量是赋予一个初始值 -
赋值擦除对象当前值,并用一个新值替代之 -
声明 (declaration)使文件可以使用别处定义的名字,变量可以被多次声明 -
定义 definition创建于名字关联的实体,变量只能被定义一次extern int i; // 声明 extern double pi = 3.1416; // 定义 int j; // 定义 -
变量的
作用域 scope全局作用域 global scope在整个程序范围内都可被使用块作用域 block scope在某一语句或者函数内可被使用
(5) 复合类型 compound type
-
引用 reference并非对象,它只是为一个已经存在的对象所起的另外一个名字int ival = 1024; int &refVal = ival; // refVal 指向ival(是ival的另一个名字) int &refVal2; // 报错:引用必须被初始化 int &refVal3 = refVal // 正确 int i = 1024, i2 = 2048; int &r = i, r2 = i2; // 正确:允许在一条语句中定义多个引用 int &refVal = 10; // 错误:引用类型的初始值必须是一个对象 -
指针 pointer存放某个对象的地址- 是对象,允许对指针赋值和拷贝
- 无须在定义时赋初值
- 不能定义指向
引用的指针
int ival = 42; int *p = &ival; // p存放变量ival的地址,指向变量ival *p = 0; // * 解引用符, ival的值被改变,而指针p并没有改变 double dval; double *pd = &dval; // 正确:pd存放dval的地址 double *pd2 = pd; // 正确:pd2与pd一样,均存放dval的地址 -
空指针 null pointer不指向任何对象int *p1 = nullptr; // 等价于 int *p1 = 0, 最好用这种方法 int *p2 = 0; // 直接将 p2 初始化为字面常量0 #include cstdlib int *p3 = NULL; // 等价于 int *p3 = 0, 尽量避免使用
(6) const 限定符
-
const对象必须初始化 -
在多个文件之间共享
const对象extern const int bufSize = 512; // 定义并初始化一个常量,可以被其他文件访问 -
const的引用const int ci =1024; const int &r1 = ci; // 正确:引用机器对象都是常量 r1 = 42; // 错误:r1 是对常量的引用,不能修改 int &r2 = ci; // 错误: 试图让一个非常量 引用 指向一个常量对象 int i = 42; const int &r3 = i; // 正确:允许将 const int & 绑定到普通 int 对象上 r3 = 0; // 错误: r3 为常量引用,不能修改其绑定的值 const int &r4 = 42; // 正确:r4 为常量引用 const int &r5 = r3 * 2; // 正确:r5 为常量引用 int &r4 = r3 * 2; // 错误:r4 不是常量引用 -
临时量 temporarydouble dval = 3.14; const int &ri = dval; // 非法 // 上一条语句等价于 const int temp = dval; // 由双精度浮点数生成一个临时的整型常量 const int &ri = temp; // 让 ri 绑定此临时量 -
指向
const的指针const double pi = 3.14; // 定义双精度浮点型常量 pi double *ptr = π // 错误:ptr 是普通指针 const double *cptr = π // 正确:cptr 可以指向双精度常量 *cptr = 42; // 错误:不能给 *cptr 赋值 double dval = 3.14; // dval 是双精度浮点数,其值可以改变 cptr = &dval; // 正确:但是不能通过 cptr 改变 dval 的值 -
const pointer:常量指针,把指针本身定为常量有点难理解int errNumb = 0; int *const curErr = &errNumb; // curErr 将一直指向 errNumb const double pi = 3.14159; const double *const pip = π // pip 是一个指向常量对象的常量指针curErr从右向左阅读:- 首先,
curErr是一个常量对象, - 其次,
curErr是一个整型指针, - 因此,
cueErr是一个指向整型的常量指针,其指向的对象不能改变。
- 首先,
pip从右向左阅读:- 首先,
pip是一个常量对象, - 其次,
pip是一个双精度浮点型指针, - 最后,
pip指向的是一个常量对象, - 因此,
pip是一个指向 双精度浮点型常量对象 的 常量指针,其指向的对象不能改变,而且也不能通过*pip改变其指向对象的值。
- 首先,
-
top-level const以及low-level const-
top-level const顶层 const,表示指针或任意对象本身是一个常量,不能改变指针指向的对象; -
low-level const底层 const,表示指针(或引用)指向(或绑定)的对象是一个常量,不能通过*point(或引用)改变指向(或绑定)对象的值,进行 copy 操作时要注意数据类型。int i = 0; int *const p1 = &i; // top-level const const int ci = 42; // top-level const const int *p2 = &ci; // low-level const const int *const p3 = p2; // (low-level const) int (top-level const) const int &r = ci; // low-level const i = ci; // 正确:top-level const 对拷贝操作无影响 int *p = p3; // 错误:p3 包含 low-level const,而 p 没有 p2 = p3; // 正确:p2 为 low-level const p2 = &i; // 正确:int * 能转换成 const int * int &r = ci; // 错误:普通的 int & 不能绑定到 const int 上 const int &r2 = i; // 正确:const int & 可以绑定到普通 int 上
-
-
constexpr常量表达式:限定符constexpr仅对指针有效,与指针所指的对象无关
const int *p1 = nullptr; // p1 是一个指向整型常量的指针,low-level
constexpr int *p2 = nullptr; // p2 是一个指向整数的常量指针,top-level
constexpr const int *p3 = nullptr; // p3 是一个指向整型常量的常量指针,(top-level) (low-level)
(7) 类型处理
-
alias declaretion别名声明有点绕using SI = Sales_item; // 等价于 typedef Sales_item SI; typedef char *pstring; const pstring cstr = 0; // cstr 是指向 char类型对象 的常量指针,而不是指向 char类型常量对象 的指针 const pstring *ps; // ps 是普通指针,它指向的对象是 指向char类型对象的常量指针 const pstring cstr = 0; // const 用于修饰 pstring,说明 cstr 是常量指针,不等价于下一行命令 const char *cstr; // const 用于修饰 char,* 是声明符,说明 cstr 是指向 char类型常量 的指针 -
auto类型说明符-
auto一般会忽略top-level const,保留low-level constconst int ci = 0, &cr = ci; auto b = ci; // b 是一个整数(ci的 top-level const特性被忽略了) auto c = cr; // c 是一个整数(cr的 top-level const特性被忽略了) auto d = &ci; // e 是一个指向 整型常量 的指针(对常量对象取地址是low-level const) -
如果希望推断出的
auto类型为top-level const,需要明确指出const int ci = 0; const auto e = ci; // ci 的推演类型是 int, e 的类型是 const int -
auto与引用设置类型为auto的引用时,初始值的top-level const特性保留;给初始值绑定引用时,此时的常量就不是top-level constint i = 0; const int ci = 0; auto &f = ci; // 正确:ci 是整型常量,因此推断的 f 也是常量 auto &g = 42; // 错误:42 不是常量,因此推断的 g 也不是常量,不能为非常量引用 绑定字面值 const auto &h = 42; // 正确:42 不是常量,但是明确指出了 h 是常量,可以为 常量引用 绑定字面值 auto &j = i; // 正确:i 的地址是常量,low-level const (不知道是否可以这样理解?) -
在一条语句中定义多个变量时,符号
&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须为同一类型int i = 0; const int ci = 0; auto k = ci, &l = i; // 正确:k 是整数,l 是整型引用,ci 和 i 的地址都是 const int (??) auto &m = ci, *p = &ci; // 正确:m 是对整型常量的引用,p 是指向整型常量的指针 auto &n = i, *ps = &ci; // 错误:i 的类型是 int,而 &ci 的类型是const int
-
-
decltype 类型指示符-
decltype返回变量的类型,包括top-level const和low-level constconst int ci = 0, &cj = ci; decltype(ci) x = 0; // x 的类型是 const int decltype(cj) y = x; // y 的类型是const int&, y 绑定到变量 x decltype(cj) z; // 错误:z 是一个引用,必须初始化 -
decltype与引用int i = 42, *p = &i, &r = i; decltype(r + 0) a; // 正确:表达式的结果类型为 int decltype(r) b; // 错误:r 的类型为 int&,必须初始化 decltype(*p) c; // 错误:*p 的类型为 int&,必须初始化 decltype((i)) d; // 错误:(i) 的类型为 int&,必须初始化 // decltype((variable)) 的结果永远是 引用
-
(8) 自定义数据结构
-
structstruct Sale_data {}; -
头文件保护
# ifndef SALES_DATA_H // 判断变量是否定义,当且仅当变量为定义时为真 # define SALES_DATA_H // 将 SALES_DATA_HATA_H 设为预处理变量 # include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; # endif // 当检查 # define 结果为真时,遇到 # endif 指令结束 -
structstruct Sale_data {}; -
头文件保护
# ifndef SALES_DATA_H // 判断变量是否定义,当且仅当变量为定义时为真 # define SALES_DATA_H // 将 SALES_DATA_HATA_H 设为预处理变量 # include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; # endif // 当检查 # define 结果为真时,遇到 # endif 指令结束
2万+

被折叠的 条评论
为什么被折叠?



