C++ PRIMER PLUS (9) 内存模型和名称空间
第九章 内存模型和名称空间
9.1 单独编译
头文件:包含结结构声明和使用这些结构的函数原型。
源代码文件:包含与机构有关的函数代码。
源代码文件:包含调用与结构相关的函数的代码。
头文件中包含的内容:
- 函数原型
- 使用
#define
或const
定义的符号常量 - 结构声明
- 类声明
- 模板声明
- 内联函数
- 多个库的连接:在连接编译模块时,请确保所有对象文件或库都是有同一个编译器生成的。因为C++标准允许每个编译器设计人员以他认为合适的方式实现名称修饰。
9.2 存储持续性、作用于和连接性
自动变量:在函数中声明的变量
静态变量:在函数定义外定义和使用static
定义的变量
动态变量:用new
和delete
分配和删除的变量
9.2.1 作用域和连接
作用域为局部的变量只在定义它的代码块({
,}
之间)可用。
在函数原型作用域中使用的名称只在包含参数列表的括号内可用。
9.2.2 自动存储持续性
局部变量名和全局变量名相同时,将暂时隐藏之前的全集定义。
关键字auto用于定义默认状态向为自动的变量,有时可用来向读者澄清代码的含义,比如程序中他一创建了一个自动变量,它将覆盖全局定义。
编译器使用堆栈来管理自动内存。
用register关键字来声明局部变量将提醒编译器通过使用CPU寄存器来处理该变量,但编译器并不一定会满足上述请求。
注意:寄存器变量没有内存地址。
9.2.3 静态持续变量
如果没有显式初始化,编译器将把它设置为0。
只能使用常量表达式来初始化静态变量:
int x; // x set to 0
int y = 49; //49 is a constant expression
int z = 2 * sizeof(int) + 1;// also a constant expression
int m = 2 * z; // incalud, z not a constant
通常情况下应使用局部变量,在需要知晓时才传递数据。
对于外部链接性变量,有且只有一个文件包含了该变量的外部定义。其他文件要使用该变量,必须在引用声明中使用关键字extern
。
如果文件定义了一个静态外部变量,其名称与另一个文件中声明的常规外部变量相同,则在该文件中,静态变量将隐藏常规外部变量。
当吧作用域解析操作符::
放在变量名称前面是,表示使用变量的全局版本。
将static
限定符用于全局变量时,该变量的链接性将为内部的,只能在其所属文件中使用。
如果初始化了静态局部变量,则程序只在启动时进行一次初始化。
通常,编译器去假设未被修改的值在两次使用时之间不会发生变化,将该值缓存,以优化。volatile
声明相当于告诉编译器,不要进行这种优化(因为硬件可能修改变量)。
struct data
{
char name[30];
mutable int accesses;
};
const data veep = {"Claybourne Clodde", 0,…};
strcpy(veep.name, "Joye Joux"); //not allowed
veep.accesses++; //allowed
veep
的const
限定符禁止程序修改veep
的成员,但accesses
成员的mutable
说明符是的accesses
不受这种限制。
const
全局变量的链接性为内部的,因此可以在所有文件中使用相同的声明
若希望某个常量的链接性为外部的,必须在所有使用该变量的文件中使用extern
关键字来声明它
extern const int states = 50; // external linkage
可以再函数原型中使用关键字extern
来指出函数是在另一个文件中定义的,不过这是可选的。
还可以使用关键字static
将函数的链接性设置为内部的,必须同时在原型和函数定义中使用该关键字。
static int private (double x);
…
static int private (double x);
{
…
}
如果定义了一个和库函数同名的函数,编译器将采用程序员定义的版本。
9.2.6 语言链接性 (如:函数名翻译)
extern "C" void spiff(int);
extern void spoff(int);
extern "C++" void spaff(int);
第一个原型使用C语言链接性,第二个原型默认使用C++链接性,第三个显式使用C++链接性。
9.2.7 存储方案和动态分配
在函数中用来跟踪动态内存的自动和静态指针变量遵循之前的存储方案,在函数结束时被释放,而new分配的内存会一直保留在内存当中,如果将指针的链接性声明为外部的,则在文件中后面的函数都可以使用它。
float *p = new float[20];
9.3 布局new操作符
char buffer1[50];
char buffer2[500];
struct chaff
{
char dross[20];
int slag;
};
int main()
{
…
p2 = new (buffer1) chaff;
p4 = new (buffer2) int [20];
…
}
上述代码中,从buffer1
中分配空间给结构chaff
,从buffer2
中分配空间给一个int
数组。