【摘要】 9.1 单独编译
头文件中常包含的内容:
函数原型使用#define或const定义的常量
结构声明
类声明
模板声明
内联函数
头文件防护
9.2 存储持续性、作用域、链接性
存储持续性
自动存储持续性静态存储持续性 : 在程序整个运行过程中都在
…
9.1 单独编译
-
头文件中常包含的内容:
- 函数原型
- 使用#define或const定义的常量
- 结构声明
- 类声明
- 模板声明
- 内联函数
头文件防护
9.2 存储持续性、作用域、链接性
-
存储持续性
- 自动存储持续性
- 静态存储持续性 : 在程序整个运行过程中都在
- 线程存储持续性
- 动态存储持续性 : new创建,delete释放
自动存储持续性
· 没有链接性
1、自动变量的初始化
2、自动变量和栈
3、寄存器变量
register int count_fast;
//在C++11中只是显式地指出变量是自动的。
//目前使用它的唯一原因是,指出程序员想使用一个自动变量,这个变量可能与外部变量名称相同
静态持续变量
-
有三种链接性
- 外部链接性(可在其他文件中访问)
-
在代码块外面声明,不用加static关键字 在其他文件中使用外部变量,只需要在一个文件中定义,在其他文件中,使用extern声明 ::warming,::作用域解析运算符放在变量名前边时,表示使用该变量的全局版本
- 内部链接性(只能在当前文件中访问)
-
在代码块外面声明,需要加static关键字 在两个文件中可以定义两个名称相同的变量,不违反当定义原则
- 无链接性(只能在当前函数或代码块中访问)
-
在代码块内部声明,需要加static关键字 如果初始化了静态局部变量,则程序只在启动时进行一次初始化。以后在调用函数时,将不会像自动变量那样再次初始化。
说明符和限定符
register
static
extern
thread_local
mutable
thread_local指出变量的持续性与其所属的线程的持续性相同
-
cv-限定符
const 和 volatile
volatile 表明即使代码没有对内存单元进行修改,其值也可能发生变化。 -
mutable
表明即使结构(或类)变量为const,其某个成员也可以被修改。 -
const
在默认情况下全局变量的链接性是外部的,但const全局变量的链接性为内部。(因此可以放在头文件中)
如果想要外部链接性,可在定义时使用extern来覆盖默认的内部链接性
函数和链接性
所有函数的储存持续性都自动为静态的,默认链接性外部
使用该函数必须包含该函数原型
可以使用static将函数的链接性设置为内部的,使之只能在一个文件中使用。必须同时在原型和函数定义中使用
static int private(double x);
static int private(double x){
cout << "private" << endl;
}
内联函数不受单定义规则的约束,这允许程序员能够将内联函数的定义放在头文件中。
语言链接性
extern "C" void spiff(int);//使用C语言链接性
extern void spoff(int); //使用C++链接性
extern "C++" void spaff(int);//使用C++链接性
存储方案和动态分配
前面方案不适合动态内存分配,其分配和释放顺序要取决于new和delete在何时以何种方式被使用。
通常编译器使用三块独立的内存:自动变量、静态变量、动态存储
extern float * p_fees;
//可以在其他函数中使用当前指针
- 使用new进行初始化
int *pi = new int (6); //小括号可以赋初始值 double * pd = new double (99.99); //列表初始化 常规结构或者数组 struct where{double x; double y; double z;} where * one = new where {2.5, 4.5, 4,4}; int * ar = new int [4] {2,4,6,7}; int * pin = new int {6};//单值也可以
- new失败时
引发异常 std::bad_alloc - new:运算符、函数和替换函数
// 分配函数 // new和new [] 分别调用如下函数 void * operator new (std::size_t); void * operator new[](std::size_t); // 释放函数 // delete 和 delete [] 分别使用如下函数 void operator delete (void *); void operator delete [](void *);
- 定位new运算符
new运算符的变体,可以指定要使用的位置。#include <new> char buffer1[50]; int main(){ int *p4 = new (buffer1) int[20]; }
void 指针可以指向任意类型的数据,就是说可以用任意类型的指针对 void 指针对 void 指针赋值。例如:
int *a;
void *p;
p=a;
- 定位new的其他形式
int* p1 = new int; int* p2 = new(buffer) int; int* p3 - new(buffer) int[40];
9.3 名称空间
概念:声明区域、潜在作用域、作用域
名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中,因此在默认情况下,在名称空间中声明的名称的链接性为外部的(除非他引用了常量)。
通过域解析运算符::,使用名称空间来限定该名称。
- using 声明和using 编译指令
- 为名称空间创建别名
namespace mvft = my_very_favorite_things;
- 未命名的名称空间
namespace{ int ice; int bandycoot; }
这种方式是链接性为内部的静态变量的替代品
文章来源: blog.csdn.net,作者:Miical,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/m0_50998563/article/details/116171596