《C++ Primer 第五版》学习笔记
《C++ Primer 第五版》学习笔记
以下为 Chapter1、Chapter2
C++是如何工作的
源文件-> 编译器-> 链接-> 可执行程序
每一个源文件在编译后都会生成.obj文件 ,通过链接就可以将所有obj文件生成一个可执行文件。
例如#include <iostream>
,#
符号后面跟的都是预处理语句。
预处理语句是在实际编译之前处理。
#include
实际上就是寻找一个文件,将此文件内容拷贝到现在文件中,这就是
头文件
项目中的每个cpp文件都会被编译,但头文件不会被编译。编译器会给每个cpp文件生成对应的obj文件,链接器将他们合并成一个exe文件。
C++编译器是如何工作的
预处理阶段编译器会遍历所有的预处理语句并对其处理,常用的预处理语句有include
if
ifdef
pragma
。
.obj文件是二进制的机器码,如果我们想查看对应的汇编代码,可以在VS的项目属性里,C/C++
--> Output File
--> Assembler Output
--> Assembly-Only Listing
C++链接器是如何工作的
编译器可以对不同 .cpp 文件生成对应 .obj 文件,而链接器需要将这些 .obj 问价链接起来,并确定入口程序(默认入口程序是main函数),最终生成 .exe 可执行程序。
当我们遇到 为解决的外部符号
错误时,就是链接器找不到需要的东西。
未调用的函数,链接器不会调用
复合类型:引用
引用:为对象起的别名。
示例代码
1 | // 引用 |
代码输出
1 | a: 8 |
例如上面代码,其中 b 是 a 的引用,相当于给变量 a 重新起了一个名字 b 。
&b 必须初始化,而且后续不能修改
- 定义引用时,把引用和他的初始值绑定在一起,而不是将初始值拷贝给使用。
- 引用本身不是对象,所以不能定义引用的引用。
复合类型:指针
对地址的封装,本身就是一个对象
**定义指针 int *p,p为一个指针对象。**
可以使用取地址符(&) 获取指针所封装的地址。
**可以使用解引用符(*)利用指针访问对象,示例如下**
示例代码
1 |
|
示例输出
1 | // 变量p里面存放的数据 |
复合类型:空指针
初始化
C++11:
int* p = nullptr;
int* p = 0;
int* p = NULL; // 需引入cstdlib
void* 指针
纯粹的地址封装,与类型无关。可以用于存放任意对象的地址。一般用在返回值类型。
指向指针的指针
如下图,ppi -> pi -> ival
其中 ppi 存放 pi 的地址,pi 存放 ival 的地址, ival 存放数字1024。
指针的引用
指针是对象,可以引用
例如:
1 | int i = 1024; |
const 限定符
- 使用const对变量的类型加以限定,变量的值不能被改变。
- const对象必须初始化(其他时候不饿能出现在等号左边)
- 默认状态下,const对象仅在文件内有效,如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
例:
1 | // 0204-1.cpp |
编译:g++ 0204.cpp 0204-1.cpp
这样是可以成功运行并输出a的值的。
const指针
指针是对象,也可以限定为常量(必须初始化)。
**把*放在 const 之前,说明指针是一个常量。不变的是针织本身的值,而非指向的那个值。**
顶层const:便是变量本身是一个常量。
底层const:表示指针所指向的对象是一个const。
常量表达式(const expression)
指不会改变并且在编译过程中就能得到计算结果的表达式。
例如:const int maxSize = 100;
constexpr
- C++11,允许将变量声明为constexptr类型,以便由编译器验证变量的值是否是一个常量表达式。
- 一定是常量
- 必须用常量表达式初始化
- 例如:
constexpr int maxSize = 100;
或指针类型constexpr int* p = nullptr;
- 自定义类型、IO库、string等类型不能被定义为constexpr。
typedef
为了提高可读性,给类型起个别名。
auto
C++11,让编译器通过初始值推断变量类型。
decltype类型说明符
- 选择并返回操作数的数据类型。
- 只要数据类型,不要值。
例如:decltype (f()) sum = x;
含义为:拿出函数
f() 的返回值类型,定义sum 并赋值为 x;
自定义数据结构
类定义:可以使用class或struct。
区别: struct是public的,class是private的。
编写自己的头文件
预处理变量有两个状态:已定义、未定义
1 |
|
如果没有 ifndef 、define 、endif
在预处理时会出现重复处理导致运行出错。