一些基本概念
定义(definition) vs 声明(declaration) :
定义是指给出关于变量/结构/类/方法/函数的完整信息。
- 对class, struct, 要求了struct里面的所有成员。
- 对于函数和方法来说, 定义是指实现了函数的body.
- 对于变量来说,要给出变量的类型。
一旦定义完了,这个类/结构的size就可以定下来了。
Declaration: 声明. 只是告诉编译器有这么一个东西。
几个例子
int a; 定义, 需要分配内存。
struct MyStruct { // 定义
int a;
double b;
}
extern int b; 声明, 编译器不需要给分配内存
extern string str1; 声明
struct MyStruct; 声明
编译
编译过程可以分为四个阶段
- Preprocess: 预处理, 替换, DEFINE/INCLUDE, header files 之类
- Compile: 转换成汇编文件 .s 文件. 输入是.cpp文件, 不含.h文件。
- Assemble: 转换成二进制文件 .o文件
- Link: 转换成可执行文件。
简而言之,preprocess 预处理,替换; compile, 编译生成 .s文件(汇编文件),仍然是可以人读的; assemble再把.as文件转成.o文件, 这时就是纯二进制码了; linker再把一堆.o文件链接在一起生成一个可执行文件。
一些小知识点
声明不会被编译。因为声明只是声明。
Toolchain
A collection of tools.
Compiler: clang(LLVM), g++(GCC). Can do both Compile and Assemble.
Linker: lld(LLVM), ld(GCC)
C++ preprocessor, Macro -> temp
把宏给替换掉, #
Compiler -> prog1.s
assembler -> prog1.o
Linker -> executable file
2
Preprocessor:
替换
#define, #undefine,
#ifdef
#ifndef
Compile
什么样的东西可以被编译的?
.cpp文件可以被编译同时被生成东西 (.o文件)
.h文件即使被编译也不能生成什么东西,h文件里面的内容只是一个knowledge
int a; 会分配一个内存
extern int a; 不会分配内存, 什么都没有, 只是一个声明.
Linker
undefined reference to SomeClass
Undefined symbol to some variable
g++ -c a.cpp
g++ -c b.cpp
g++ a.o, 没法编译 这里是link了 假设a.cpp里面引用到了b.cpp里的变量,此时就无法编译, 需要两个放在一起编译
g++ b.o a.o
静态链接 Vs 动态链接
静态链接库, lib1.a, lib2.a
把所有东西放在一起, 速度快, 容易布署。但是体积大,link时间长。
动态链接
启动的时候启动一下linker, 读一下ld, (操作系统的linker), 把每个lib做一个内存映射
less memory, less storage, 执行慢, 难deploy, 变量没有初始化
大公司一般用静态链接; 因为大公司一般一台机器只跑一个服务,换成动态链接库也省不了什么内存。
header (*.h) vs implementation
header只放knowledge类型的东西 , 不能执行的,不需要分配内存的。 不会被编译器生成什么东西的文件。
inline函数可以放在h文件里, inline不是一个share的东西, 是一个knowledge.
Cpp文件里放全局变量定义,全局函数的实现,类的方法的实现。cpp文件里放那些可以产生实际runnable code的source code, 或者需要分配内存的。