c++存储持续性、作用域和链接性
1.c++使用三种不同的方案进行数据的存储,这些方案的区别就在于数据保留在内存中的时间
●自动存储持续性:
在函数定义中声明的变量(包括函数参数)的存储持续性为自动类型。
☉作用域:局部,在包含定义它的函数内部有效。
☉链接性:没有链接性,只能在定义它的函数内部使用,不能在其他函数中使用。
☉内存对自动类型变量的管理:常用的方法是留出一段内存,并将其视为栈,以管理变量的增减。
●静态存储持续性:
在函数定义外定义的变量和使用static关键字定义的变量为静态类型。
☉链接性:
▼外部链接性:变量定义在函数定义之外,并且没有用static修饰。
作用域:整个程序,可以在各个文件中使用该变量。
▼内部链接性:变量定义在函数定义之外,但是用static修饰。
作用域:在包含这个变量定义的文件的函数中可用。但在其他文件的函数中不可用
▼无链接性:变量定义在函数定义之内,用static休息,与auto的差别在于static修饰的
变量一直存在在内存中,而auto类型的变量使用完后就在内存中销毁了。
作用域:只在变量定义的函数体内有效。
☉内存对静态存储类型变量的管理:由于静态变量的数目在程序运行期间是不变的,因此编译器将分配固定的内存 单元来存储所有的静态变量,这些变量在整个程序执行期间一直存在。
●动态存储持续性:
使用new分配的内存将一直存在,直到使用delete将其释放或函数结束。
2.auto变量,静态变量举例:
文件结构:
file1.cpp源代码:
#include using namespace std; int error = 3; //外部变量,在file1.cpp和file2.cpp中都可以使用 static int count = 9; //静态变量,在file1中可以使用,在file2中不能使用 int myfun(); int fun(); int main() { int num = 5; //auto类型变量,仅在main函数中能够使用,无链接性 cout << count << endl; //可以使用 cout << num << endl; return 0; } int fun() { cout << count << endl; //可以使用count,因为count有内部链接性 cout << error << endl; //可以使用 //cout << num << endl; //不能使用,因为num是在main中定义,无链接性 return 0; }file2.cpp源代码:
#include using namespace std; extern int error; //extern static int count; //不能用,因为count是file1.cpp中定义的只具有内部链接性的变量,只能在file1.cpp中使用,不具有外部链接性 int myfun() { cout << error << endl; return 0; }
3.mutable的使用
作用:可以用它来指出,即使结构体(或类)变量为const,用mutable关键字修饰的变量的值也是可以改变的。
举例:
struct data { char name[30]; mutable int level; }; const data veep = {"zhangfei", 1}; veep.level++; //这句是有效的,虽然veep被定义为const,但是level成员前有mutable修饰,所以可以修改
4.在c++中,被const修饰的全局变量的链接性为内部链接
如:
const int fingers = 10; int main() { ... }fingers这个变量只能在该文件中使用,不能在该项目的其他文件中使用。
5.函数和链接性:
●所有函数都是静态的,即整个程序的执行期间一直存在
●在默认情况下,函数的链接性为外部链接,即可以在文件间共享
●可以使用关键字static将函数的链接性设置为内部链接,即只能在一个文件中使用,在函数声明和函数定以前都要加上static
static int private(double x); ... static int private(double x) { ... }
●单定义规则也适用于非内联函数,内联函数不接受这条规则的约束,这允许程序员能够将内联函数的定义放在头文件中
6.定位new运算符
通常,new运算符负责在堆中找到一个足以能够满足要求的内存块。new运算符还有另外一种变体,能够指定要使用的位置,被称为定位new运算符。要使用定位new运算符,需要包含头文件new。需要注意的是,delete只能用于删除指向常规new运算符分配的堆内存。
常规new运算符和定位new运算符举例:
#include #include //要使用定位new运算符,需要包含头文件new using namespace std; const int n = 5; const int buf = 512; int buffer[buf]; int main() { int *pi1, *pi2, *pi3, *pi4; pi1 = new int[buf]; //pi1在内存中找一块能使用的内存,位置不定 pi2 = new (buffer) int[buf]; //pi2使用定位new,所分的内存是从buffer开始 cout << "calling new and placement new:\n"; cout << "memory addresses:\n"; cout << " heap: " << pi1 << " static: " << pi2 << endl; cout << "memory contents:\n"; for(int i = 0; i < n; i++) pi1[i] = pi2[i] = 1000 + 20 * i; for(int i = 0; i < n; i++) { cout << pi1[i] << " at " << &pi1[i] << " "; cout << pi2[i] << " at " << &pi2[i] << endl; } cout << endl; cout << "calling new and placement new a second time:\n"; cout << "memory contents:\n"; pi3 = new int[buf]; //pi3在内存中找一块能使用的内存,位置不定 pi4 = new (buffer) int[buf]; //pi4使用定位new,所分的内存是从buffer开始,所以pi4显示的地址跟pi2一致 for(int i = 0; i < n; i++) pi3[i] = pi4[i] = 1000+ 40 * i; for(int i = 0; i < n; i++) { cout << pi3[i] << " at " << &pi3[i] << " "; cout << pi4[i] << " at " << &pi4[i] << endl; } delete [] pi1; delete [] pi3; //释放常规new分配的内存,定位new分配的内存不能使用delete return 0; }运行结果:
下一篇: C++文件流状态的判别与定位