1、单独编译
头文件:包含结构声明和使用这些结构的函数的原型
源文件:包含与结构实现有关的函数的代码;
源文件:包含调用与结构相关的函数的代码。
一般的程序组织结构如上所示分为三个部分,这种形式避免了 结构 的修改不影响其基本调用,编译也不需要全部重新编译。
同一个文件只能将同一个头文件包含一次,下属代码避免了这种问题。
#ifndef ***_H_ #define ***_H_ ... #endif // 防止上述问题
2、存储持续性、作用域和链接性
自动存储持续性:函数定义中声明的变量。 执行时创建,执行结束时释放 无链接性(仅可在当前函数/代码块中访问)
静态存储持续性: static 关键词声明和函数定义外定义的变量。 整个运行期都存在 外部链接性(可在其它文件访问)、内部链接性(仅当前文件)、无链接性
线程存储持续性(C++11):关键词thread_local 声明。 生命周期与线程一样长
动态存储持续性:new运算符分配。 delete运算符释放或者程序结束 (自由存储/堆)
3、变量存储方式
存储描述 | 持续性 | 作用域 | 链接性 | 如何声明 |
自动 | 自动 | 代码块 | 无 | 代码块中 |
存储器 | 自动 | 代码块 | 无 | 代码块中,使用 register 关键字 |
静态、无链接 | 静态 | 代码块 | 无 | 代码块中,使用 static 关键字 |
静态、外部链接性 | 静态 | 文件 | 外部 | 不在任何函数内 |
静态、内部链接性 | 静态 | 文件 | 内部 | 不在任何函数内,使用关键字 static |
3、自动存储持续性
函数声明中的参数和函数内部变量 局部作用域 没有链接性
自动变量的数目随着程序的开始和结束而增减 在程序中单独开辟的 栈 中进行操作 栈的顺序为后进先出
关键词 register 显示指示该变量为自动变量。
4、静态持续变量
不同的声明方式决定了变量的链接性①、外部链接性 -- 必须在代码块的外面声明;②、内部链接性 -- 必须在代码块的外部使用 static 关键字声明;③、无连接性 -- 在代码块内部使用 static 关键字声明。
静态变量在固定的内存中 存在于整个程序的执行期间。 若未使用 常量 进行显示初始化,将自动被初始化为 0 。
5、使用 extern 关键字将其他文件的静态外部链接性变量引用到 当前文件,但是该变量不可以进行初始化,初始化导致变量定义的行为。
注意:同名的局部变量可以隐藏全局变量 作用域解析运算符(::)可以在此情况下仍使用全局变量。
全局变量的缺点:由于对数据访问的任意性,可能会导致程序不可靠;优点:多个函数使用同一个数据块(不需要进行参数的传递)。
6、静态变量该程序段结束(离开作用域),也会继续存在与内存中(位置是固定的,在程序结束后内存才会被回收)。
再次运行到该程序段,不会再次初始化(只会初始化一次)
7、存储说明符:
thread_local、auto、register、static、extern、mutable。
上述说明符 除了 thread_local 可以和 static或extern 配合使用外,其他的说明符只可以单独使用。
thread_local:线程存储周期;register:寄存器变量;static:静态变量声明;
mutable:修饰结构变量或类变量的成员时,即使声明为 const ,也可以修改该变量。
8、cv-限定符
const:内存初始化后不再被修改;
volatile:即使程序没有修改内存,其值也可能被修改(硬件修改)。此限定符表示每次读取该变量的实际存储位置,而非读取内存中的变量副本。
9、const 结合 extern
const int finger; // 变量定义为内部链接性
extern const int finger; // 不可以进行初始化
上述代码和 extern int fingers; // 一样不可以初始化
但是其在每个文件中存在着各自的一组变量,并不是共享同一组变量。
extern const int fingers = 5; // 变量定义并为外部链接性,并覆盖了原有的变量
此种定义确保各文件之间为共享同一组变量。
10、函数和链接性
函数的存储连续性全部为静态(函数内不可以定义函数 ),链接性为外部(可以在文件之间共享)
可以使用 extern 明确指示该函数在其他文件中定义,也可以使用 static 限定函数仅可以在该文件内使用(其他文件中可以有同名文件)。
函数调用顺序:
11、语言链接性
由于语言的标准不同,C/C++语言的编译器针对函数名的翻译不一样。
可以使用查询约定使用的函数原型
extern “C” void spiff(int); // 使用 C 语言链接性 用于名称查找
extern void spiff(int); // 使用 C++ 语言链接性 用于名称查找
extern “C++” void spiff(int); // 使用 C++ 语言链接性 用于名称查找
12、动态分配:new、delete 运算符
动态内存分配: new运算符申请,delete运算符销毁变量
int *pi = new int (6); // 申请并初始化 int 型变量
int *pin = new int [4]{2,4,6,8}; // 申请整形数组并初始化 还可以用 {} 初始化结构、初始化单值
new函数申请内存失败:返回空指针、现在将会引发异常 std::bad_alloc。
new、delete 运算符可以针对性的进行重载。
13、定位运算符 new
char buf[50];
chaf *p2 = new (buf) chaf; // chaf 为自定义结构体 新申请的 chaf 变量位于内存中的 buf 内
上述的 p2 不可以使用 delete 运算符释放(buf的内存为静态内存,在delete运算符的适用范围之外)
new 可以接受两个参数
int *pi = new int ; // new(sizeof(int))
chaf *p2 = new (buf) chaf[40]; // new(40*sizeof(chaf),buf)
14、名称空间
声明区域:可以在其中进行声明的区域(代码块、整个文件)
潜在作用域:变量的潜在作用域从声明位置到声明区域结束;
变量在潜在作用域内可以被其他变量隐藏。
名称空间:通过定义一种新的声明区域来创建命名的名称空间,可以提供一个声明名称的区域,不同名称空间之间的相同名称不会冲突。
15、命名空间使用方式 ----- 命名空间::变量名;
using 命名空间; // using 编译指令 导入命名空间中的全部名称 --- 可能会导致命名空间中的变量覆盖 程序中的其他变量
using 命名空间::变量名; // using 声明 使用命名空间中的某变量,后续直接使用该变量
命名空间可以嵌套
未命名的名称空间表示:其中的名称从声明位置到该声明区域末尾都可以使用