C++学习笔记(一)

环境搭建以及《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环境并配置,如下图

img

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_tUnicode 字符16 位
char32_tUnicode 字符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 开头的整数代表八进制,以 0x0X 开头的代表十六进制数,例如,可以用以下几种形式表示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 不是常量引用
    
  • 临时量 temporary

    double 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 = &pi;			// 错误:ptr 是普通指针
    const double *cptr = &pi;	// 正确: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 = &pi;	// 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 const

      const 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 const

      int 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 constlow-level const

      const 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) 自定义数据结构

  • struct

    struct 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 指令结束
    
  • struct

    struct 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 指令结束
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值