头文件(内容)
- 函数原型
- 结构声明
- 类声明
- 模板声明
- 符号常量定义
- 内联函数
头文件搜索:
- #include<>在存储标准头文件的计算机的文件系统中查找
- #include"" 首先在工作目录或者编译器规定的目录中查找,然后再查找标准头文件。
头文件管理:不允许在一个文件中两次调用头文件。解决方法如下:
#ifndef name
// 名称定义
#define name
// 内容
#endif
定义一个名称,如果名称被定义过,则不执行#ifndef 和#endif 之间的数据 。
4种存储方法:自动存储,静态存储,线程存储,动态存储(内存分配)
三个属性:
- 连续性:
- 作用域:局部作用域,全局作用域(文件作用域),类作用域,函数原型作用域,名称空间作用域
- 链接性:外部链接性,内部链接性,无链接性
自动存储
变量:自动变量,局部代码块变量(在代码块中的代码块定义的变量)
持续性:在代码块被执行开始到代码块结束。
作用域:从代码声明开始到代码块结束。
链接性:没有
初始化:一般的初始化
存储位置:放在栈中
静态变量(常规外部变量(全局变量,有时也称外部变量),静态外部变量,静态局部变量)
存储位置:在计算机中开辟一个区域。
初始化:静态初始化和动态初始化
- 静态初始化包括:零初始化,常量表达式初始化。sizeof(int)属于常量
- 常量表达式:只由常量组成的表达式
- constexpr和const:const既表达常量,也表达只读的属性。constexpr只表达常量的属性。
常规外部变量:定义在函数之外,且链接性是外部。单定义准则:在所有的文件中只可以定义一次。
file1中:
int a = 1;
file2中:
extern int a;
// 此处不能初始化,否则就是定义变量和int a = 1;一样
静态外部变量:使用static修饰的外部变量,意味着链接性为内部。
静态局部变量:使用static修饰的局部变量,其中static意味着持续性是整个文件。
int a = 1; // 外部变量
static int a = 1; // 静态外部变量
void function(void)
{
static int a; // 静态局部变量
}
存储说明符和cv限定符:
存储说明符:
- auto:自动判别类型。后置返回类型。
- register:自动变量的标识
- static:静态变量声明
- extern:引用声明
- mutable:对于结构中的值,即是结构声明了const,但是其内部变量仍然可变。
struct name{
int a;
mutable double b;
};
const name bob = {1, 2.0}
其中bob.a内容不能变化,但是bob.b内容可以变化
- thread_local 类似于static,static是在程序执行期间的持续性,而thread_loacl是在线程执行期间的持续性。
cv限定符:
- const:表示只读属性。const定义的符号全局符号常量的链接性是内部的,所以不会违反单一变量原则。
- volatile:表示存储的数据即是没有程序代码对内存进行修改,其值仍然会发生变化。
当指向硬件的指针,其内部包含硬件的时间信息,则硬件会修改。或者网络共享的文件,也会被其他人修改。
volatile解决的问题是:对于在很多的代码块内多次使用的参数,编译器会将其放在寄存器当中,从而达到加快运行的目的,而这时如果发生非程序代码更改,则信息无法同步。使用volatile则可避免以上的优化。
函数
函数的持续性:静态。链接性:外部。
静态函数:在原型和定义中加入static,其链接性是内部的。
内联函数可以多次定义:但是c++要求不同文件的相同内联函数定义必须相同。
c++找函数:
- 判断函数是否是静态函数,如果是则在文件中寻找。
- 在项目中寻找(项目中定义的函数最好不要和标准库中的函数相同)
- 在标准库文件中寻找
c++语言链接性:
名称修饰:c++当中的函数为了应对函数重载,所以将函数名和特征标组合并进行修改,形成一个独特的名字,用于函数搜索。对于不同的编译器,得到的名字不同。
C语言库函数和C++的名称修饰不同:所以C++允许对名称修饰方式进行转换:
extern "C" void spiff(int); // C语言的方式
extern void spaff(int); // C++方式
extern "C++" void spaff(int); // C++
动态存储:
new实现动态存储:其返回的指针可以使用静态存储或者自动存储。
new初始化:
new int (4);
new int [4] {1,2,3,4};
new 失败时:使用std::bad_alloc标识
new声明分配函数和释放函数:
// 分配函数
void * operator new(std::size_t);
void * operator new[](std::size_t);
// std::size_t是整形的大小
// 释放函数
void operator delete(void *);
void operator delete[](void *);
// new和delete的函数用法
void * ps = new(sizeof(int));
void * ps = new(n*sizeof(int));
delete (ps);
定位new运算符:
new (buffer) int ;
new (buffer) int [4];
特点:
- 不和delete连用
- new分配的空间类型和buffer定义的类型可以不同
- 可以放在不同的地址
- 定位new运算符可以重载。
名称空间:不同名称空间同名变量不冲突,且允许程序的其他部分使用该名称空间。全局名称空间包含用户定义的名称空间。
限定名称:即有装饰的名称。非限定名称:就是没有装饰的名称。
using声明,using编译:去除原来名称空间的特性,变成非限定名称。
using声明可以代替变量声明。
using编译和using声明本质区别:
namespace jill
{
double a;
}
void function()
{
using namespace jill;
double a; // 不冲突
}
void function1()
{
using jill:a;
double a; // 冲突
}
未命名的名称空间:类似于静态全局变量。
名称空间函数:(对于函数的原型和定义要放在同一个名称空间中)
using name::function_name; // 可以引用所有的重载函数
拥有名称空间之后的一些习惯:
- 使用名称空间去替代外部变量和静态外部变量。
- 对于标准库文件c++11要求都放在std名称空间中
- 尽量使用using声明和作用域解析运算符。