目录
- 将原来的程序分为三部分:头文件、主函数和子函数
- 静态持续性、外部链接性
- 静态持续性、内部链接性
- 静态存储持续性、无链接性(涉及到一个静态变量在字符串输入的应用)
- 存储方案和动态分配
- 定位new运算符
- 名称空间特性
- 名称空间示例
- 名称空间的使用规范
将原来的程序分为三部分:头文件、主函数和子函数
/*
01)原来的源程序可以分为三部分:
A 头文件:包含结构声明和使用这写结构的函数的原型
B 源代码文件:包含与结构有关的函数的代码(主函数)
C 源代码文件:包含调用与结构相关的代码(子函数)
02)头文件中常包含的内容:
函数原型(函数声明)、使用#define或const定义的符号常量
结构声明、类声明、模板声明、内联函数
03)在包含头文件时,我们使用"coordin.h",而不是<coordin.h>。
如果头文件包含在尖括号内,则c++编译器将在存储标准头文件的主机系统的文件系统中查找;
如果头文件包含在双引号中,则编译器将首先查找当前的工作目录或源代码目录;如果没有在
那里找到头文件,则将在标准位置查找,因此在包含自己的头文件时候,应该使用双引号而不是尖括号
*/
存储类型、作用域和链接性
01)自动存储:在函数内部定义的常规变量使用自动存储空间,被称为自动变量,这意味着它们在所属的函数被调用时
自动生成,在该函数结束时消亡。自动变量通常存储在栈中,这意味着其中变量依次加入到栈中,而在离开栈时,
将按相反的顺序释放这些变量,这被称为"后进先出(LIFO)",因此在程序执行的过程中,栈将不断的减小或增大。
02)静态存储:是一种在整个程序执行期间都存在的存储方式,使变量称为静态的方式有两种:一种是在函数外满定义
变量,另一种是在声明变量时使用关键字stctic。
03)动态存储:new是delete提供的存储方式。它们管理一个内存池,这在c++这被称为自由存储空间(free store)或
堆(heap),该内存池同用于自动变量和自动变量的内存是分开的。
04)作用域: 描述了名称在文件(翻译单元)的多大范围内课件。例如在函数定义的变量可在该函数中使用,但在
其他函数则不可以;而在函数外面定义的变量则可以在所有函数中使用。
05)链接性: 描述了名称如何在不同单元间共享。链接性为内部的名称只能由一个文件中的函数共享。
自动变量没有连接性,因为它们不能共享。
自动存储持续性
01)在默认情况下,在函数中声明的函数参数和变量的存储持续性为自动,作用域为局部,没有链接性。也就是说
如果mian()函数中声明了一个texas的变量,在子函数oil()中也声明了一个texas变量,则创建两个独立的变量,
只有在定义它们的函数中才可以使用它们。对oil()函数中的texas变量执行的任何操作不会影响main()函数中的
texas变量,反之亦然。例如如下代码块
int main()
{
int teledeli = 5;
//定义代码块
{
int teledeli = 23;
teledeli = teledeli+1;
cout<<"Hello"<<teledeli<<endl; //打印的是24
}
teledeli = teledeli+1;
cout<<"Hello"<<teledeli<<endl; //打印的是6
}
02)寄存器变量: 关键字register最初是由c语言提出的,它建议编译器使用CPU寄存器来存储自动变量,这旨在
提高访问变量的速度。
register int cout_fast; //声明一个寄存器变量
静态持续变量&static的两种用法
01)c++为静态存储持续性变量提供了三种链接性:外部链接性(可在其他文件中访问,用static声明)、
内部链接性(只能在当前文件中访问,用static声明)和无连接型(只能在当前函数代码块或子函数
中访问,用static声明)。这三种链接性的变量在整个程序执行期间都存在,
与自动变量相比,他们的寿命更长。由于静态变量在程序运行期间是不变的,故程序不需要使用特殊的装
置(如栈)来存储他们,编译器只需要给他们分配固定的内存块即可。另外,如果没有显式的初始化静态变量,编
译器将把他们设置为0。在默认情况下,静态数组和结构将每个元素或成员的所有位设置为0.
现举例说明如何创建三种链接类型的变量:
...
int global = 1000; //global具有外部链接性,在程序的其他文件只也可以使用
//如何在其他cpp文件中使用另外一个cpp文件中的外部变量(即上面的变量global)?使用关键字extern,接下来将会介绍
//下面一句中的static表示的是内部链接性,变量是静态持续性
static int one_file = 50; //one_file具有内部链接性,只能在包含上述代码的文件中使用它
int main()
{
....
}
void fun1(int n)
{
//此时static表示的是存储持续性
static int count = 0; //count没有链接性,作用域为局部,这意味着只能在fun1只使用它
int llama = 0; //与llama不同的是,即使fun1()函数没有被执行,count也留在内存中
}
02)static的两种用法:
A 用于局部声明(函数内声明变量),以指出变量时无连接型的静态变量时,static标示的是存储持续性;
B 用于代码块外的声明时,static表示的是内部链接性,而变量已经是静态持续性了
总结如下表:
静态持续性、外部链接性
01)变量的定义方法(两种):
A 定义声明(简称定义):它给变量分配存储空间
B 引用声明(简称声明):它不给变量分配存储UKon关键,因为它引用已有的变量,
引用变量使用关键字extern,且不能给变量初始化,否则声明变为定义,导致分配存储空间
double up; //定义
extern int blem; //声明,不能初始化
extern char gr = 'A'; //定义,虽然使用了extern,但是给变量初始化了
02)一方面,在每个使用外部变量(在函数外定义的变量)都必须声明它,
另一方面:变量只能定义一次(单定义规则)
03)如果在多个cpp文件中使用main.cpp或其他cpp文件中的外部定义,只需在一个cpp文件中包含该变量
的定义(单定义规则),但在其他使用改变量的其他cpp文件中,都必须使用关键字extern声明它,如:
//file01.cpp
extern int cats = 20; //extern可以省略,加上也是可以的
int dogs = 22;
int fleas;
//file02.cpp
extern int cats; //使用extern之后,在file02.cpp之后就可以使用file01.cpp中的cats变量
extern int dogs; //使用extern之后,在file02.cpp之后就可以使用file01.cpp中的dogs变量
//file03.cpp
extern int cats; //使用extern之后,在file03.cpp之后就可以使用file01.cpp中的cats变量
extern int dogs; //使用extern之后,在file03.cpp之后就可以使用file01.cpp中的dogs变量
extern int fleas; //使用extern之后,在file03.cpp之后就可以使用file01.cpp中的fleas变量
1 //external.cpp 2 //compile with support.cpp 3 4 #include <iostream> 5 6 using namespace std; 7 8 double warming = 0.3; //定义外部变量(全局变量),在support.cpp中也可以使用的 9 10 void update(double dt); //声明一个函数,该函数在support.cpp中定义 11 void local(); //声明一个函数,该函数在support.cpp中定义 12 13 int main() 14 { 15 cout << "Global waiming is " << warming << endl; 16 update(0.1); //调用support.cpp中定义的函数 17 cout << "Global waiming is " << warming << endl; 18 local(); //调用support.cpp中定义的函数 19 cout << "Global waiming is " << warming << endl; 20 21 system("pause"); 22 return 0; 23 }
1 //surpport.cpp 2 //compile with external.cpp 3 4 #include <iostream> 5 6 void update(double dt); //声明一个函数 7 void local(); //声明一个函数 8 9 using std::cout; 10 using std::endl; 11 12 extern double warming; //声明引用变量,即声明在外部文件(external.cpp)中定义的变量 13 14 void update(double dt) 15 { 16 extern double warming; //声明引用变量,即声明在外部文件(external.cpp)中定义的变量,由于在函数外已经使用extern声明了warming,所以此处不写这一句也是可以的 17 warming = warming + dt; //对在external.cpp中的外部变量进行修改,此处的修改会在external.cpp中保存 18 cout << "Updating global warming to " << warming << endl; 19 } 20 21 void local() 22 { 23 double warming = 0.8; //声明一个局部变量 24 cout << "Local warming is " << warming << endl; 25 cout << "But global warming is " << ::warming << endl; //c++提供了作用域解析运算符::,放在变量前该运算符表示使用全局版本 26 27 }
程序说明:
01) c++提供了作用域解析运算符::,放在变量前该运算符表示使用全局版本
02) 另外在external.cpp中定义的外部(全局)变量,如果要在support.cpp中使用,但是必须是在support.cpp中函数外部用extern声明一下
03)如果在外部定义了一个warming变量,在一个子函数内也定义了一个相同名字的变量warming,那么执行到该子函数的时候,子函数内的
warming会覆盖掉外部定义的warming变量
在external.cpp文件中执行的结果:
静态持续性、内部链接性
01)在函数外定义的变量具有外部链接性,可以在不同程序文件之间共享数据
在函数内定义或者是用关键字static定义的变量具有内部连接性,只能在本cpp文件内共享用该变量
名称空间提供了另外一种共享数据的方法
02)下面介绍一种错误的做法:
//file01.cpp
int errors = 20;
//file02.cpp
int errors = 5;//这里将会报错,因为同时在两个cpp文件中同时定义了一个名字相同的变量,是不合法的
03)改进(使用static关键字):
//file01.cpp
int errors = 20; //外部(全局)变量errors具有外部链接性
void main()
{
....
}
//file02.cpp
static int errors = 5; //这样是允许的,因为这个errors变量具有内部连接性
void support()
{
....
}
04)在多程序文件中,可以在一个文件(且只能在一个文件)中定义一个外部变量。使用该变量的其他文件使用
关键字extern声明该变量。
05)可以将作用域为单独某一个cpp文件的变量设置为静态的(使用static声明),就不必担心其名称与外部变量
发生冲突。即防止出现02)类似的错误。
//该程序演示了c++佮处理链接性为外部和内部的变量
1 //twofile1.cpp 该文件件包含了main() 2 //compile with twofile2.cpp 3 //该程序演示了c++佮处理链接性为外部和内部的变量 4 #include <iostream> 5 6 int tom = 3; //定义外部(全局)变量,链接性为外部 7 int dick = 30; //定义外部(全局)变量,链接性为外部 8 static int harry = 300; //定义静态外部变量,链接性为内部,即harry的作用域为twofile1.cpp,不能作用于外部cpp文件 9 10 void remote_access(); //在twofile2.cpp中定义的函数 11 12 int main() 13 { 14 using namespace std; 15 16 cout << "外部变量tom的地址:" << &tom << " tom的值为:" << tom << endl; 17 cout << "外部变量dick的地址:" << &dick << " dick的值为:" << dick << endl; 18 cout << "静态外部变量harry的地址:" << &harry << " harry的值为:" << harry << endl; 19 remote_access(); //调用在twofile2.cpp中定义的函数 20 21 system("pause"); 22 return 0; 23 }
1 //twofile2.cpp 2 //compile with twofile1.cpp 3 4 #include <iostream> 5 6 extern int tom; //使用twofile1.cpp中的外部变量tom 7 static int dick = 10; //使用自己cpp文件中定义的静态全局变量dick 8 int harry = 200; //不会与twofile1.cpp中定义的静态外部变量harry冲突,因此此处的harry的作用域为全部cpp文件 9 10 void remote_access() 11 { 12 using namespace std; 13 14 cout << "在子函数remote_access()中:" << endl; 15 cout << "外部变量tom的地址:" << &tom << " tom的值为:" << tom << endl; 16 cout << "twofile2.cpp中静态外部变量harry的地址:" << &harry << " harry的值为:" << harry << endl; 17 }
执行结果:
静态存储持续性、无链接性(涉及到一个应用,要看一下的)
01)无链接性的局部变量:将static限定符用于在代码块中定义的变量。在代码块使用static时,将导致局部
变量的持续性为静态的。这意味着该变量只在该代码块内可用,但它在该代码块不处于活动状态时仍然存
在。因此在函数调用之前,静态局部变量的值将保持不变。(静态局部变量适用于再生---可以将用静态局
部变量存储银行密码,传递到下一个地方去)。
02)如果初始化了静态局部变量。则程序只在启动时进行一次初始化,以后再调用该函数时,将不会像自动变量
那样再次被初始化。
1 #include <iostream> 2 3 const int ArSize = 10; //定义一个值不可被改变的外部(全部)变量,加了const之后,ArSize的作用域为该cpp文件,相当于加了static 4 5 void strcount(const char* str); //声明一个子函数 6 7 int main() 8 { 9 using namespace std; 10 11 char input[ArSize]; //定义一个c风格字符串数组,最多存储9个字符 12 char next; //定义一个字符变量,作用域为main() 13 14 cout << "请输入一行字符:"; 15 cin.get(input, ArSize); //输入到字符串数组input中,最多可输入ArSize-1个字符,有一个位置要为空字符' '保留 16 17 while (cin) //如果输入的字符数小于ArSize,那么最后的回车键会被保留在输入流中。 18 { //如果输入流中有字符,那么cin的返回值一直是true(因为没有接收的变量) 19 cin.get(next); //如果输入的字符多于9个,那么输入到next中去 20 while (next != ' ') 21 cin.get(next); //一直将多输入的字符接收完 22 strcount(input); //子函数调用 23 cout << endl; 24 cout << "请输入一行字符:"; 25 cin.get(input, ArSize); 26 } 27 cout << "Bye" << endl; 28 29 system("pause"); 30 return 0; 31 } 32 void strcount(const char* str) 33 { 34 using namespace std; 35 36 static int total = 0; //只会初始化一次,以后被修改的值会被保留下来 37 int count = 0; //每次调用该函数的时候count都会被初始化一次 38 39 cout << """ << str << "" contains "; //其中"表示显示",表示消除歧义的意思 40 while (*str != '