Cpp基础
C++编程介绍

头文件到底是个什么东西?
头文件其实跟源文件没什么区别,都是C++的源代码
因为在编译的时候头文件中的内容会被直接copy进cpp文件,但是有的时候头文件会互相包含,这可能就会造成在一份源码中copy两次同样的头文件,这也是为什么需要ifndef endif 或者#pragma once的用处。
头文件相互包含总会有一个文件在另一个文件中被忽略。
因为预处理时include是将包含的文件中的代码插入到当前代码里,文件是不能包含自己的,如果相互包含编译器只能取舍一下,否则是不可能正常通过的。如果遇到这种情况就需要对头文件进行重构,修改其包含关系
所以头文件里最好只放变量和函数的声明,而不能放它们的定义(如果多个函数都include定义,那么就会出错了)。
但有三个例外!
其一,就是const/static可以在头文件的中定义,因为const/static默认为全局数据区,仅在当前文件有效,即使被多个文件包含也只会定义一次。
其二,就是内联函数的定义。内联函数和普通函数的区别在于编译阶段编译器需要知道内联函数的内部具体实现(才能够将其展开插入源代码),因此将内联函数放于头文件甚至有好处的。
其三,就是类的定义。程序在创建一个类对象的时候,编译器只有在类定义完全可见的情况下才能够对其进行布局(如内存分配、数据成员有哪些、函数接口有哪些),且也可以将函数成员的实现也放在头文件中,因为如果函数成员在类的定义体中被定义,那么就默认这个函数是内联的。

- 预处理器
C/C++的预处理器其实就是一个词法(而不是语法)预处理器,其主要完成文本替换、宏展开以及删除注释等,完成这些操作之后,将会获得真正地**“源代码”**。
常见的include语句即是一个预处理器命名,在预处理器中它将所有的头文件包含进来。
(该步骤的文件扩展名为.i)
- 编译器
在这一步骤,将.i文件翻译为.s,得到汇编程序语言,值得注意的是所有的编译器输出的汇编语言都是同一种语法。
注:内联函数就是在这一环节“膨胀”进源码的,它的作用即在于:不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处,适用于功能简单,规模较小又使用频繁的函数。递归函数无法内联处理,内联函数不能有循环体,switch语句,不能进行异常接口声明。仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
- 汇编器
将.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件.o中(把汇编语言翻译成机器语言的过程)。
- 链接器**
链接的主要内容就是将各个模块之间相互引用的部分正确的衔接起来。它的工作就是把一些指令对其他符号地址的引用加以修正。链接过程主要包括了地址和空间分配、符号决议和重定向。
**符号决议:**有时候也被叫做符号绑定、名称绑定、名称决议、或者地址绑定,其实就是指用符号来去标识一个地址。比如说 int a = 6;这样一句代码,用a来标识一个块4个字节大小的空间,空间里边存放的内容就是4.
重定位:重新计算各个目标的地址过程叫做重定位。
gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去。
函数库一般分为静态库和动态库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,**但在运行时也就不再需要库文件了。**其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,**而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。**动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。
.txt(代码段)
.data(全局静态已初始化变量)
.bss(全局未初始化变量)
heap(堆)
stack(栈)
内存分段见下图:

其中,.data用于存放初始化过的全局变量。若全局变量值为0,为了优化编译器会将它放在**.bss段**中。
.bss段被用来存放那些没有初始化或者初始化为0的全局变量。bss段只占运行时的内存空间而不占文件空间。在程序运行的整个周期内,.bss段的数据一直存在。
-
内存栈区: 存放局部变量名;
-
内存堆区: 存放new或者malloc出来的对象;
-
常数区: 存放局部变量或者全局变量的值;
-
静态区: 用于存放全局变量或者静态变量;
-
代码区:二进制代码。
https://blog.csdn.net/jirryzhang/article/details/79518408
C++基础知识
全局/局部静态变量?
静态变量都存放于全局数据区,都在程序退出时才销毁,两者唯一的区别就在于作用域不同,全局变量全局可见,而局部静态变量仅在局部区域可见。
作用域和生命周期是从两个不同的角度:时间和空间对变量进行描述。
作用域,即是该变量可被引用的范围;
生命周期即是该变量从初始化到销毁的时间;
一个程序的内存分为代码区、全局数据区、堆区、栈区,不同的内存区域,对应不同的生命周期。
全局变量
- 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用域所有源文件。)
- 生命周期:程序运行期间一直存在
- 引用方法:其他文件中使用必须用extern关键字声明引用的全局变量
- 内存分布:全局数据区
- 注意:如果在两个文件中都定义了相同名字的全局变量,连接出错:变量重定义
全局静态变量
- 作用域:文件作用域(只在被定义的文件中可见。)
- 生命周期:程序运行期间一直存在
- 内存分布:全局数据区
- 定义方法:static关键字,const关键字
- 注意:只要文件不互相包含,在两个不同的文件中是可以定义完全相同的两个静态变量的,它们彼此独立,只作用在各自文件中。
局部静态变量
- 作用域:局部作用域(只在局部作用域可见)
- 生命周期:程序运行期间一直存在
- 内存分布:全局数据区
- 定义方法:局部作用域中用static定义
- 注意:值被初始化一次,多线程中需加锁保护)
局部变量
- 作用域:局部作用域(只在局部作用域可见)
- 生命周期:程序运行出局部作用域即被销毁
- 内存分布:栈区
函数指针与指针函数
边学变写 无效!
先不写了,等我看了书有收获有想法再写—