头文件
-
如果文件名包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统的中查找。如果文件名包含在双引号中,则编译器将在当前目录下查找。
-
使用条件编译防止多次包含头文件
#ifndef XXX_H_ #define XXX_H_ ... #endif
存储持续性,作用域和链接性
存储描述 | 持续性 | 作用域 | 链接性 | 如何声明 | 存储位置 |
---|---|---|---|---|---|
自动 | 自动 | 代码块 | 无 | 在代码块中 | 栈中 |
寄存器 | 自动 | 代码块 | 无 | 在代码块中,使用关键字register | 寄存器中 |
静态,无链接性 | 静态 | 代码块 | 无 | 在代码块中,使用关键字static | 内存块 |
静态,外部链接性 | 静态 | 所有文件 | 外部 | 不在任何函数中 | 内存块 |
静态,内部链接性 | 静态 | 本文件 | 内部 | 不在任何函数内,使用关键字static | 内存块 |
-
如果定义一个静态外部链接性的变量,其他文件在使用时,需要引用声明使用关键字extern,且不进行初始化。
-
作用域解析运算符
int a=5; int main() { int a=3; cout<<a<<endl; cout<<::a<<endl;//作用域解析运算符,此时的a为全局变量的a }
-
说明符
- register 用于在声明中指示寄存器存储,而在C++11中,它只是显式地指出变量是自动的。
- static 表示内部链接性。
- extern 表面是引用声明,即声明引用在其他文件定义的变量。
- thread_local(C++11新增) 指出变量的持续性与其所属的线程的持续性相同。thread_local变量之于线程,犹如常规静态变量之于整个程序。
- mutable 用来指出,即使结构(或类)变量为const,其某个成员也可以被修改。
struct student { char name[30]; mutable int score; }; int main() { const student a={"guo shen",100}; a.score++; cout<<a.name<<' '<<a.score<<endl; }
-
cv-限定符
- volatile
- 即使程序代码没有对内存单元进行修改,其值也可能发生变化(可能受硬件影响)
- 如果不使用volatile变量,在再次访问之间编译器可能会认为值没有变化,从而进行优化(如将值放在寄存器中缓存起来)
- 使用volatile变量相当于告诉编译器,不要进行这种优化
- const – 不能修改的内存
- const 对全局变量的链接性有影响 – const全局变量的链接性为内部的。
- 这也是const变量能写在头文件而没有多重定义的原因
- 若想使用链接性为外部的const变量,则可以再在前面加extern进行定义,但其他文件使用此变量必须也要用extern关键字进行声明
extern const int maxn = 100;
- volatile
-
函数的链接性
- 函数默认为外部静态的 即默认是extern的
- 可使用 static 关键字将其链接性设置为内部的
- 必须同时在原型和定义中使用static
- 内部静态函数将覆盖外部函数
-
语言链接性
- C语言对函数名的矫正使用的约定与C++不同, 可用函数原型指出其使用的约定
extern "C" void fun(int); // 使用C语言的约定 extern void fun(int); // 使用C++的约定 extern "C++" void fun(int); // 使用C++的约定 -- 显式指出
-
动态分配内存
-
new运算符
void * operator new(size_t); //used by new void * operator new[](size_t);//used by new[]
-
定位new运算符
- new 负责在堆上找一块满足要求的内存块
- 定位new 能指定要使用的位置
- 设置内存管理规程,处理需要通过特定地址进行访问的硬件,在特定位置创建对象等
- 使用
#include <new> char buff[50]; int* p = new (buff) int[20]; // 从buff中分配一个包含20个int的数组 //不能使用delete来释放内存 void* operator new(std::size_t, void* position);//定位new运算符的重载
名称空间
-
using 编译指令和using声明之比较
- 如果某个名称已经在函数声明了,则不能用using声明导入相同的名称。
- 如果使用using编译指令,名称空间相当于全局的,那么局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样。不过仍可以使用作用域解析运算符。
-
未命名的名称空间
namespace { int cnt=5; } //=static int cnt=5; int main() { cout<<cnt<<endl; }