1、掌握C+语言在结构化程序结构化程序设计(非面向对象)方面对C语言扩充的性能,为编写面向对象面向对象的C+程序打下基础。2.1 C+的特点的特点2.2 C+语言的文件扩展名语言的文件扩展名2.3 注释符注释符2.4 名字空间名字空间2.5 C+语言的输入输出语言的输入输出2.6 变量的定义变量的定义2.7 强制类型转换强制类型转换2.8 动态内存的分配与释放动态内存的分配与释放2.9 作用域运算符作用域运算符:2.10 引用引用2.11 const修饰符修饰符2.12 字符串字符串2.13 C+语言中函数的新特性语言中函数的新特性习题习题2.1 C+的发明人的发明人 Bjarne Stroust
2、rup(本贾尼斯特劳斯特卢普)博士,C+语言之父,1950年出生于丹麦,1979年在英国剑桥大学获得计算机科学博士学位计算机科学博士学位,AT&T、贝尔实验室和ACM成员。1979年,B.S开始开发一种语言,当时称为“C with Class”,1983年演化为C+。1998年,ANSI/ISO C+标准建立,同年,B.S推出了其经典著作The C+Programming Language的第三版。Stroustrup博士是C+语言的设计者和第一位实现者,该语言业已成为世界上最通用的支持面向对象技术面向对象技术的程序设计语言。2.1 C+开发工具的历史开发工具的历史90年代初的年代初的Turb
3、o C+2.1 C+开发工具的历史开发工具的历史90年代中期的年代中期的Borland C+for dos 2.1 C+开发工具的历史开发工具的历史90年代中期的年代中期的Borland C+Builder for Win 2.1 C+开发工具的历史开发工具的历史21世纪的世纪的visual C+6.0 2.1 C+开发工具的历史开发工具的历史visual studio 2010 2.1 C+的特点的特点 C+语言既保留了语言既保留了C语言的有效性、灵活性、语言的有效性、灵活性、便于移植等全部精华和特点,又添加了便于移植等全部精华和特点,又添加了,具有强大的编程功能,可方便地构,具有强大的编程
4、功能,可方便地构造出模拟现实问题的实体和操作;编写出的程序造出模拟现实问题的实体和操作;编写出的程序具有结构清晰、易于扩充等优良特性,适合于各具有结构清晰、易于扩充等优良特性,适合于各种应用软件、系统软件的程序设计。用种应用软件、系统软件的程序设计。用C+编写编写的程序可读性好,生成的代码质量高,运行效率的程序可读性好,生成的代码质量高,运行效率仅比汇编语言慢仅比汇编语言慢10%20%。为了使编译器能够区别是为了使编译器能够区别是C C语言还是语言还是C+C+语言,语言,C+语言体系规定用语言体系规定用“”(意即意即作作为为C+语言源文件的扩展名以区别于语言源文件的扩展名以区别于C语言用的语言
5、用的“.C”文件扩展名。虽然仅差两个字母,但编译时文件扩展名。虽然仅差两个字母,但编译时的处理却相差甚远。的处理却相差甚远。“cpp”的文件扩展名与操的文件扩展名与操作系统无关。与作系统无关。与C+语言源文件相关的头文件扩语言源文件相关的头文件扩展名一般仍用展名一般仍用“”,但有些操作系统也有规定使,但有些操作系统也有规定使用用“.hpp”充当头文件扩展名的。充当头文件扩展名的。1.1.段注释:段注释:/*/2.2.单行注释:单行注释:/当只做单行注释时便当只做单行注释时便可用可用“/”符号表示从此符号起至符号表示从此符号起至行尾行尾均均为行注释内容。为行注释内容。3.3.程序编译时将忽略所有
6、的注释内容。程序编译时将忽略所有的注释内容。名字空间域是随标准名字空间域是随标准C+而引入的。它相当而引入的。它相当于一个更加灵活的文件域(于一个更加灵活的文件域(全局域全局域),可以用),可以用花括号把文件的一部分括起来,并以关键字花括号把文件的一部分括起来,并以关键字namespacenamespace开头给它起一个名字:开头给它起一个名字:namespace ns1 float a,b,c;fun1()花括号括起来的部分称声明块。声明块中可以包括:花括号括起来的部分称声明块。声明块中可以包括:类、变量(带有初始化)、函数(带有定义)等。在域外类、变量(带有初始化)、函数(带有定义)等。在
7、域外使用域内的成员时,需加上名字空间名作为前缀,后面加使用域内的成员时,需加上名字空间名作为前缀,后面加上域操作符上域操作符“:”。这里添加了名字空间名称的成员名被。这里添加了名字空间名称的成员名被称为限定修饰名。如称为限定修饰名。如:ns1:a,ns1:fun1()等等。等等。最外层的名字空间域称为全局名字空间域(最外层的名字空间域称为全局名字空间域(global global namespace scopenamespace scope),即文件域。),即文件域。名字空间域可分层嵌套,同样有分层屏蔽作用。例如:名字空间域可分层嵌套,同样有分层屏蔽作用。例如:namespace n1 nam
8、espace n2 /名字空间嵌套名字空间嵌套 class matrix/名字空间类成员名字空间类成员matrix 访问访问matrix,可写:,可写:n1:n2:matrix。使用使用using声明声明可只写一次限定修饰名。可只写一次限定修饰名。using声明以关键声明以关键字字using开头,后面是被限定修饰的开头,后面是被限定修饰的(qualified)名字空间名字空间成员名,例如:成员名,例如:using n1:n2:matrix;/名字空间类成员名字空间类成员matrixmatrix的的usingusing声明声明以后在程序中使用以后在程序中使用matrix时,就可以直接使用成员名,
9、而时,就可以直接使用成员名,而不必使用限定修饰名。不必使用限定修饰名。使用使用using指示符指示符可以一次性地使名字空间中所有成员都可以一次性地使名字空间中所有成员都可以直接被使用,比可以直接被使用,比usingusing声明方便。声明方便。usingusing指示符以指示符以关键关键字字using开头,后面是关键字开头,后面是关键字namespace,然后是,然后是名字空间名字空间名名。标准标准C+库库中的所有组件都是在一个被称为中的所有组件都是在一个被称为std的名字空间中声明和定义的。在采用标准的名字空间中声明和定义的。在采用标准C+的平台上使用标准的平台上使用标准C+C+库中的组件,
10、只要写库中的组件,只要写一个一个using指示符指示符:就可以直接使用就可以直接使用中的所有成员。中的所有成员。注意:注意:如果使用了名空间如果使用了名空间std,则在使用,则在使用#include编译预处理命令包含头文件时,必须编译预处理命令包含头文件时,必须去掉头文件的扩展名去掉头文件的扩展名.h,否则会出错。,否则会出错。C+语言另外定义了一套语言另外定义了一套流对象流对象与运算符来替代与运算符来替代C语言中对标准输入输出函数语言中对标准输入输出函数scanf和和printf的引用。的引用。C+语言的保留字为:语言的保留字为:cout“输出内容输出内容”“输入内容输入内容”;/cin为标
11、准输入流对象为标准输入流对象(默认从默认从键盘键盘输入输入)#include 输入重定向输入重定向【例例2.1】C+的输入输出举例。的输入输出举例。#include /使用名空间使用名空间std,则必须去掉,则必须去掉.h扩展名扩展名using namespace std;void main()char name10;int age;coutname;coutage;coutname is nameendl;coutage is ageendl;补充补充(写出程序执行结果,假定输入写出程序执行结果,假定输入1和和2)#include /使用名空间使用名空间std,则必须去掉,则必须去掉.h扩展
12、名扩展名using namespace std;void main()char ch1,ch2;int n1,n2;cinch1ch2;n1=ch1-0;n2=n1*10+(ch2-0);coutn2;补充补充(写出程序执行结果写出程序执行结果)#include /使用名空间使用名空间std,则必须去掉,则必须去掉.h扩展名扩展名#includeusing namespace std;void main()int n,count=0;for(n=1;n=100;+n)coutsetfill(*)setw(10)n;count+;if(count%5=0)coutendl;程序执行结果程序执行结
13、果 在在C C语言中,局部变量说明必须置于可执行代码段之前,语言中,局部变量说明必须置于可执行代码段之前,不允许局部变量声明和可执行代码混合在一起。但不允许局部变量声明和可执行代码混合在一起。但C+C+在变量的定义上作了在变量的定义上作了两种较大的改变两种较大的改变,一是允许变量的,一是允许变量的定义语句可以出现在程序的任何位置定义语句可以出现在程序的任何位置,使得局部变量的使得局部变量的定义点定义点与与使用点使用点不至于离得太远,增强程序的可读性,不至于离得太远,增强程序的可读性,而且也不必在编写某一程序块的开始时就考虑要用到哪而且也不必在编写某一程序块的开始时就考虑要用到哪些变量些变量;二
14、是;二是允许直接使用允许直接使用结构体名结构体名定义变量定义变量,这种扩,这种扩展为程序员在编程中提供了不少方便。类似地在展为程序员在编程中提供了不少方便。类似地在C+C+语语言中联合名、枚举名也可在定义后独立地作为类型名使言中联合名、枚举名也可在定义后独立地作为类型名使用。用。#includeusing namespace std;void main()struct studentint no;float math;int n;cinn;wang.no=n;cinwang.math;coutwang.no wang.mathendl;格式:格式:(数据类型数据类型)(表达式表达式)数据类型数
15、据类型 (表达式表达式)(1)(1)通过强制类型转换,得到一个所需类型的中间值,通过强制类型转换,得到一个所需类型的中间值,该中间值被引用后即自动释放。原来表达式的值类型并该中间值被引用后即自动释放。原来表达式的值类型并未改变。如下列代码段:未改变。如下列代码段:int b;float f;f=float(b);/此时变量此时变量b b仍然为仍然为int类型。类型。(2)(2)强制类型转换符优先级较高,只对紧随其后的表达强制类型转换符优先级较高,只对紧随其后的表达式起作用,而对其他部分不起作用。如表达式式起作用,而对其他部分不起作用。如表达式float(i)*f的含义是先将变量的含义是先将变量
16、i i强制类型转换为强制类型转换为float类型,然后与类型,然后与变量变量f f运算。运算。(3)(3)强制类型转换应当用在不做转换将影响表达式结果强制类型转换应当用在不做转换将影响表达式结果的正确性或精度,或不能完成相应运算的场合。而对于的正确性或精度,或不能完成相应运算的场合。而对于系统可以自动转换类型的场合,则没有必要使用。系统可以自动转换类型的场合,则没有必要使用。栈内存与堆内存栈内存与堆内存l栈空间栈空间是编译编译时分配的固定大小固定大小的内存。用于存放函数调用者的地址、返回值、保存的机器状态(用于返回)、函数参数、局部变量和临时变量等l堆内存堆内存是程序是程序运行运行时分配的时分
17、配的大小可变大小可变的内存,也称的内存,也称为为动态内存动态内存C+提供了两种方法进行内存提供了两种方法进行内存动态分配动态分配和和释放释放lmalloc()和和free()(从从C标准库中继承包含标准库中继承包含malloc.h)lnew和和delete1.new运算符运算符 指针变量指针变量 =new 数据类型数据类型;new从堆内存中为程序从堆内存中为程序分配分配可以保存某种可以保存某种类型数据类型数据的一块的一块内存空间内存空间,并返回指向该内存的,并返回指向该内存的首地址首地址,该地,该地址存放于址存放于指针变量指针变量中。中。堆内存可以按照要求进行分配,程序对内存的需求堆内存可以按
18、照要求进行分配,程序对内存的需求量随时会发生量随时会发生变化变化,有时程序在运行中可能会不再需,有时程序在运行中可能会不再需要由要由new分配的内存空间,而且程序还未运行结束,分配的内存空间,而且程序还未运行结束,这时就需要把先前占用的内存空间这时就需要把先前占用的内存空间释放释放给给堆内存堆内存,以,以后重新分配,供程序的其它部分使用。后重新分配,供程序的其它部分使用。2.delete运算符运算符运算符运算符delete用于释放用于释放new分配的内存空间,它的使用形分配的内存空间,它的使用形式为:式为:delete 指针变量;指针变量;其中的指针变量保存着其中的指针变量保存着new动态分配
19、的内存的首地址。动态分配的内存的首地址。3.注意:注意:(1)用用new获取的内存空间,必须用获取的内存空间,必须用delete进行释放;进行释放;(2)对一个指针只能调用一次对一个指针只能调用一次delete;(3)用用delete运算符作用的对象必须是用运算符作用的对象必须是用new分配的内存空分配的内存空间的间的首地址首地址。#include using namespace std;void main()int*p;p=new int;/分配内存空间分配内存空间*p=5;cout*p;delete p;/释放内存空间释放内存空间【例例2.3】new与与delete应用举例应用举例。(分析
20、运行结果分析运行结果)在用在用new分配内存的同时进行初始分配内存的同时进行初始化。使用形式为:化。使用形式为:指针变量指针变量=new 数据类型数据类型(初始值初始值);例如上例中的:例如上例中的:p=new int;*p=5;也可写成:也可写成:p=new int(5);指针变量指针变量 =new 数据类型数据类型数组大小数组大小;此时指针变量指向第一个数组元素的地址。使此时指针变量指向第一个数组元素的地址。使用用new分配数组时,不能提供初始值。使用分配数组时,不能提供初始值。使用new建立的数组变量也由建立的数组变量也由delete释放。其形式为:释放。其形式为:delete 指针变量
21、;或指针变量;或delete 指针变量;指针变量;同样,也可以用同样,也可以用new来为多维数组分配空间,来为多维数组分配空间,但是除第一维可以为变量外,其它维数都必须但是除第一维可以为变量外,其它维数都必须是是常量常量。4用用new建立数组类型的变量建立数组类型的变量 注意在使用注意在使用delete时,不用考虑数组的维数。时,不用考虑数组的维数。有时,并不能保证一定可以从堆内存中获得所需空间,有时,并不能保证一定可以从堆内存中获得所需空间,当不能成功地分配到所需要的内存时,当不能成功地分配到所需要的内存时,new返回返回0,即,即空空指针指针。因此我们可以通过判断。因此我们可以通过判断ne
22、w的返回值是否为的返回值是否为0,来,来得知系统中是否有足够的空闲内存来供程序使用。例如:得知系统中是否有足够的空闲内存来供程序使用。例如:int*p=new int100;if(p=0)cout cant allocate more memory,terminating.endl;exit(1);其中其中exit函数的作用是终止程序运行。函数的作用是终止程序运行。#include using namespace std;void main()int n;/定义数组元素的个数定义数组元素的个数 int*p;coutn;if(p=new intn)=0)cout cant allocate mo
23、re memory,terminating.endl;exit(1);/分配内存空间分配内存空间 for(int i=0;in;i+)pi=i*2;coutNow output the array:endl;for(i=0;in;i+)coutpi ;coutendl;delete p;/释放内存空间释放内存空间【例例2.4】从堆内存中获取一个整型数组,赋值后并打印出来。从堆内存中获取一个整型数组,赋值后并打印出来。通常情况下,如果全局变量与局部变量同通常情况下,如果全局变量与局部变量同名,那么局部变量在其作用域内具有较高的优名,那么局部变量在其作用域内具有较高的优先权。先权。C语言规定只能在
24、变量的作用域内使用该语言规定只能在变量的作用域内使用该变量,不能使用其他作用域中的变量,可采用变量,不能使用其他作用域中的变量,可采用C+中提供的作用域运算符中提供的作用域运算符:,它能指定所需要,它能指定所需要的作用域。的作用域。注意:注意:不能用不能用:访问访问函数函数中的中的局部变量局部变量。在。在C+语言中作用域运算符语言中作用域运算符:还用来限定还用来限定类类的的成员成员,#include using namespace std;float a=2.4;/全局变量全局变量void main()int a=8;/局部变量局部变量coutaendl;cout:aendl;/:a表示全局作
25、用域中的变量表示全局作用域中的变量a#include void main()int x10,i,j;j=0;/计数器初值赋计数器初值赋0 coutinput 10 numbers:endl;for(i=0;ixi;for(i=0;i0)j+;coutj=j;从键盘上输入从键盘上输入1010个整数,统计其中的正整数的个数个整数,统计其中的正整数的个数 程序运行结果:程序运行结果:(从键盘输入:从键盘输入:-2 3 4 -5 -3 9 -23 0 -1 21)输出:输出:j=4 用冒泡排序法对用冒泡排序法对10个数按从小到大的顺序输出个数按从小到大的顺序输出思想:冒泡法的基本思想是对数组元素做若干
26、次的思想:冒泡法的基本思想是对数组元素做若干次的遍历调整遍历调整,每次遍历都是对,每次遍历都是对相邻的两个数两两比较相邻的两个数两两比较并调整,将小的调到前头,大的调到后面并调整,将小的调到前头,大的调到后面。4739147391437914379143719第一趟循环4次43719347193471934179第二趟循环3次341793417931479第三趟循环2次3147913479第四趟循环1次5 5个数#include void main()int a11;int i,n,t;/i表示数组下标,表示数组下标,n表示遍历次数,表示遍历次数,t用来交换数据用来交换数据 coutinput
27、 10 numbers:endl;for(i=1;iai;coutendl;for(n=1;n=9;n+)for(i=1;iai+1)t=ai;ai=ai+1;ai+1=t;coutthe sorted numbers:endl;for(i=1;i11;i+)coutai;coutendl;程序运行结果:程序运行结果:input 10 numbers:1 32 13 0 23 9 45 8 19-7 the sorted numbers:-7 0 1 8 9 13 19 23 32 45#include#include void main()char str20;int i,j;cin.get
28、(str,20);j=strlen(str);for(i=j-1;i=0;i-)cout.put(stri);从键盘上输入一个字符串,然后将其逆序输出从键盘上输入一个字符串,然后将其逆序输出运行的结果是:运行的结果是:(从键盘输入:(从键盘输入:abcdefg)gfedcbal使用字符串常量来对字符数组初始化。例如char str10=student;l或者直接将花括号省略,写成如下的形式char str10=student;l注意:字符串常量所占的空间一定字符串常量所占的空间一定不能超过字符数组不能超过字符数组的长度的长度。如果字符串常量占用的空间小于数组。如果字符串常量占用的空间小于数组的
29、长度,则后面的元素自动的赋值为的长度,则后面的元素自动的赋值为0 的输出的输出 l用cout输出。格式为:cout字符串或字符数组名;l用cout流对象的put。格式为:cout.put(字符或字符变量字符或字符变量);l这种方法,每次只能输出一个字符;要输出整个字符串,应采用循环的方法#include void main()char s20=This is a string.;int i=0;while(si!=0)cout.put(si);i+;的输出的输出 l用cout流对象的write方法。格式为:cout.write(字符串或字符数组名,个数字符串或字符数组名,个数n);l其作用是输
30、出字符数串中的前其作用是输出字符数串中的前n个字符。个字符。#include void main()char s20=This is a string.;cout.write(s,4);分析该程序的输出结果的输入的输入 l利用cin直接输入。格式为:cin字符数组名字符数组名;用这种方法输入字符串时,cin只能接收空格之前空格之前的部分。也就是说,当字符串中有空格空格时,用这种方法无法接收全部的字符串。l利用cin流对象的getline方法。格式为:cin.getline(字符数组名,输入字符串的最大长度字符数组名,输入字符串的最大长度n);参数“字符数组名”是存放字符串的数组名称参数“输入字
31、符串的最大长度n”包括了字符串结束标记0在内 字符串处理函数字符串处理函数 l字符串的连接函数(strcat)调用的一般形式:strcat(char,const char);#include#include void main()char st120=qing,st2=huadaxue;strcat(st1,st2);cout字符串2,返回值0;字符串1字符串2,返回值0 l字符串、字符串2可以是字符数组也可以是字符串常量。l字符串的比较不能使用以下的形式:if(s1=s2)coutyes;只能使用该函数来进行比较。所以应该写成:if(strcmp(s1,s2)=0)coutyes;#incl
32、ude#include void main()char str120,str220,str350;cin.getline(str1,20);cin.getline(str2,20);if(strcmp(str1,str2)0)strcpy(str3,str1);strcat(str3,str2);else strcpy(str3,str2);strcat(str3,str1);coutstr3;程序运行结果:(从键盘输入:China Beijing)则输出:BeijingChina二维数组二维数组l定义的一般形式为类型说明符类型说明符 数组名数组名 常量表达式常量表达式11常量表达式常量表达式
33、22 例:int a53;表示表示a为整型二维数组,其中第一维有为整型二维数组,其中第一维有5个下个下标(标(04),第二维有),第二维有3个下标(个下标(02),数组),数组的元素个数为的元素个数为15,可以用于存放,可以用于存放5行行3列列的整的整型数据表格。型数据表格。二维数组的存储二维数组的存储 lC+语言中,二维数组在内存中默认情况下采用行优先存储(对float a23画存储示意图)l二维数组的初始化 分行对二维数组赋初值。如 int a23=1,2,3,4,5,6;对所有数据一起赋值,放在一个花括号中。如:int a23=1,2,3,4,5,6;部分元素赋值,如:int a23=1
34、,2,4;数组的元素全部赋值时,可以省略数组的第一维长度 二维数组元素输入输出例子二维数组元素输入输出例子#include void main()int i,j,a23=3,0,1,10,-4,9;for(i=0;i=1;i+)for(j=0;j=2;j+)coutendlaij=aij;程序运行结果:程序运行结果:a00=3a01=0a02=1a10=10a11=-4a12=9编写程序,将一个二维数组中行和列元素互换,存到另编写程序,将一个二维数组中行和列元素互换,存到另一个二维数组中。设数组:一个二维数组中。设数组:思想:需要定义两个数组思想:需要定义两个数组行列交换实质上是将数组元素的行
35、列交换实质上是将数组元素的行列下标相互交换行列下标相互交换二维数组,必须要逐个的进行交换,所以要用到了二维数组,必须要逐个的进行交换,所以要用到了双重双重循环循环语句语句 a=b=159268862951#include void main()int a23=1,5,9,2,6,8;int b32,i,j;coutArray a:endl;/输出原来数组的数据输出原来数组的数据 for(i=0;i2;i+)for(j=0;j3;j+)coutaij ;bji=aij;/将两个数组元素相互交换将两个数组元素相互交换 coutendl;coutArray b:endl;/输出交换后的数据元素输出交
36、换后的数据元素 for(i=0;i3;i+)for(j=0;j2;j+)coutbij ;coutendl;程序运行结果:Array a:1 5 92 6 8Array b:1 25 69 8综合程序设计举例综合程序设计举例#include void main()int i,j;float a1010,sum=0,x;coutinput n*n Matrix:endl;for(i=0;i10;i+)for(j=0;jx;aij=x;for(i=0;i10;i+)sum=sum+aii+ai9-i;coutthe sum is:sumendl;综合程序设计举例结果综合程序设计举例结果 一条对角线
37、元素的下标特点是:一条对角线元素的下标特点是:行列下标相等行列下标相等。另一。另一条对角线下标特点是:条对角线下标特点是:行列下标之和等于行列下标之和等于9。在每一行的每一列中找出这样的元素然后把它加到变在每一行的每一列中找出这样的元素然后把它加到变量量sum中去。中去。程序运行结果:程序运行结果:input 3*3 Matrix:1 3 52 4 6 7 8 9the sum is:30思考题思考题 从键盘输入一个字符串判断是否为从键盘输入一个字符串判断是否为“回文回文”比如:比如:ABCBA#include#include void main()char str60;int i,j;cin
38、.get(str,60);i=0;j=strlen(str)-1;while(stri=)i+;/寻找前面第一个不是空格的字符寻找前面第一个不是空格的字符 while(strj=)j-;/寻找后面第一个不是空格的字符寻找后面第一个不是空格的字符 while(ij&stri=strj)/前后对应逐个的比较前后对应逐个的比较 i+;j-;if(ij)coutNoendl;elsecoutYesendl;程序运行结果:从键盘输入:程序运行结果:从键盘输入:studeduts输出的结果:输出的结果:Yesj从字符串的最后一个从字符串的最后一个元素开始,所以初值元素开始,所以初值为为strlen(str
39、)-1 开始比较时,将字符开始比较时,将字符串前后的空格过滤掉串前后的空格过滤掉 引用是引用是C+语言的一个特殊的数据类型描述,用于语言的一个特殊的数据类型描述,用于在程序的不同部分使用在程序的不同部分使用两个以上的变量名两个以上的变量名指向指向同一地同一地址址,使得对其中任一个变量的操作实际上都是对同一,使得对其中任一个变量的操作实际上都是对同一地址单元进行的。在这种两个以上变量名的关系上,地址单元进行的。在这种两个以上变量名的关系上,被声明为被声明为引用类型引用类型的变量名则是实际变量名的的变量名则是实际变量名的别名别名。引用运算符为引用运算符为&,声明引用的一般形式为:,声明引用的一般形
40、式为:数据类型数据类型&引用变量名引用变量名=变量名;变量名;或或 数据类型数据类型&引用变量名引用变量名=变量名;变量名;或或 数据类型数据类型&引用变量名引用变量名=变量名;变量名;对引用进行操作,实际上就是对被引用的变量进行对引用进行操作,实际上就是对被引用的变量进行操作。引用不是值,操作。引用不是值,不占存储空间不占存储空间,声明引用时,目,声明引用时,目标的存储状态不会改变。引用一旦被初始化,就标的存储状态不会改变。引用一旦被初始化,就不能不能再重新赋值再重新赋值。【例例2.5】引用举例。引用举例。(图示变量及其引用并分析运行结果图示变量及其引用并分析运行结果)#include vo
41、id main()int num=50;int&ref=num;ref+=10;coutnum=numendl;cout ref=refendl;num+=40;cout num=numendl;coutref=refendl;说明:说明:(1)在一行上声明多个引用型变量在一行上声明多个引用型变量(函数函数)名时,要在每名时,要在每个变量个变量(函数函数)名前都冠以名前都冠以“&”符号。符号。(2)引用引用不是变量不是变量,所以引用本身不能被修改,在程序,所以引用本身不能被修改,在程序中对引用的存取都是对它所引用的变量的存取。中对引用的存取都是对它所引用的变量的存取。(3)一个变量被声明为引用
42、时必须进行一个变量被声明为引用时必须进行初始化初始化,除非这,除非这个引用是用作个引用是用作函数的参数函数的参数或或返回值返回值,为引用提供的初始,为引用提供的初始值应为值应为变量变量(包括对象包括对象)。引用一旦被初始化引用一旦被初始化,就不能再重就不能再重新赋值新赋值。如。如ref=&j;但但ref=j是允许的。是允许的。(4)由于引用不是变量,所以,不能说明引用的引用,由于引用不是变量,所以,不能说明引用的引用,也不能说明数组元素的类型为引用数组,或指向引用的也不能说明数组元素的类型为引用数组,或指向引用的指针。例如:指针。例如:int&a5;/错误错误int&*p;/错误错误由于指针也
43、是变量,因此可以说明对由于指针也是变量,因此可以说明对指针变量指针变量的的引用引用。例如:例如:int*a;int*&p=a;int b;p=&b;/a指向变量指向变量b(5)引用与指针不同。指针的内容或值是某一变量的引用与指针不同。指针的内容或值是某一变量的内内存单元地址存单元地址,而,而引用引用则与初始化它的则与初始化它的变量变量具有具有相同相同的的内内存单元地址存单元地址。指针是个。指针是个变量变量,可以把它,可以把它再赋值再赋值成其它的成其它的地址,然而,建立引用时必须进行初始化并且决地址,然而,建立引用时必须进行初始化并且决不会再不会再指向其它不同的变量。指向其它不同的变量。地址地址
44、(6)要注意区分引用运算符和地址运算符的区别要注意区分引用运算符和地址运算符的区别。例。例如:如:int num=50;int&ref=num;int*p=&ref;/&在赋值号在赋值号右边右边为为地址地址运算符运算符(7)可以用一个引用可以用一个引用初始化初始化另一个引用另一个引用。例如:。例如:int num=50;int&ref1=num;int&ref2=ref1;ref2=100;/num被修改为被修改为100其中其中ref2也是对也是对num的引用。的引用。(8)可以把可以把函数的参数说明成引用函数的参数说明成引用以建立函数参数的以建立函数参数的引用传递引用传递方式方式好处:好处:
45、C+的引用传递方式的的引用传递方式的实参实参和和形参形参指向指向同一内存地址同一内存地址,l减少值传递引起的减少值传递引起的数据堆栈复制数据堆栈复制l避免地址传递引起的避免地址传递引起的地址溢出错误地址溢出错误lC+提供提供引用引用的主要用途就是建立的主要用途就是建立函数参数函数参数的的引用传递方式引用传递方式C语言的函数参数传递只能采用语言的函数参数传递只能采用值传递值传递和和地址传递地址传递三种传递方式比较的例子三种传递方式比较的例子交换两个数交换两个数用一般变量作为参数交换两个数用一般变量作为参数交换两个数采用传值方式采用传值方式#include void swap(int x,int
46、y)int t;t=x;x=y;y=t;void main()int a=1,b=2;cout交换前交换前,a=a,b=bendl;swap(a,b);cout交换后交换后,a=a,b=bendl;运行结果:运行结果:交换前交换前,a=1,b=2交换后交换后,a=1,b=2交换功能未实现。交换功能未实现。说明采用传值方式时,实参不受影响说明采用传值方式时,实参不受影响 用指针变量作为参数交换两个数用指针变量作为参数交换两个数采用传址方式采用传址方式#include void swap(int*x,int*y)int t;t=*x;*x=*y;*y=t;void main()int a=1,b=
47、2;cout交换前交换前,a=a,b=bendl;swap(&a,&b);cout交换后交换后,a=a,b=bendl;运行结果:运行结果:交换前交换前,a=1,b=2交换后交换后,a=2,b=1采用传地址方式传递参数。采用传地址方式传递参数。在函数中改变了形参,就是改变了实参,因为他们是在函数中改变了形参,就是改变了实参,因为他们是指向指向同一地址同一地址的指针变量。的指针变量。因此交换功能实现因此交换功能实现用引用作为参数交换两个数用引用作为参数交换两个数采用传引用方式采用传引用方式#include void swap(int&x,int&y)int t;t=x;x=y;y=t;void
48、main()int a=1,b=2;cout交换前交换前,a=a,b=bendl;swap(a,b);cout交换后交换后,a=a,b=bendl;运行结果:运行结果:交换前交换前,a=1,b=2交换后交换后,a=2,b=1采用传引用方式传递参数。采用传引用方式传递参数。函数中的函数中的是主调函数中是主调函数中的引用。的引用。在函数中改变了在函数中改变了形参形参,就是改变了,就是改变了实参实参,因为他们指,因为他们指向向同一地址同一地址。因此交换功能实现因此交换功能实现地址传递和引用传递的比较。地址传递和引用传递的比较。引用作为参数,主调函数可引用作为参数,主调函数可直接使用直接使用变量名变量
49、名地址作为参数,主调函数要将地址作为参数,主调函数要将传递过去传递过去引用作为参数,函数可对引用作为参数,函数可对形参变量形参变量地址作为参数,函数需通过地址作为参数,函数需通过指针指针对对(9)有空指针,无空引用有空指针,无空引用(10)引用不能用数据类型来初始化引用不能用数据类型来初始化。如:。如:int&ref=int;/error(11)函数调用可以作为左值函数调用可以作为左值(函数返回值函数返回值为为引用类型引用类型)引用表达式是一个左值表达式,因此它可以出现在形、实参数引用表达式是一个左值表达式,因此它可以出现在形、实参数的任何一方。若一个函数返回了的任何一方。若一个函数返回了引用
50、引用,那么该,那么该函数的调用函数的调用也可以被也可以被赋值赋值。一般说,当返回值。一般说,当返回值不是不是本函数内定义的本函数内定义的局部变量局部变量时就可以返时就可以返回一个回一个引用引用。在通常情况下,。在通常情况下,引用返回值引用返回值只用在需对只用在需对函数的调用重函数的调用重新赋值新赋值的场合,也就是对的场合,也就是对函数的返回值重新赋值函数的返回值重新赋值的时候。避免将局的时候。避免将局部作用域中变量的地址返回,就使部作用域中变量的地址返回,就使函数调用表达式作为左值函数调用表达式作为左值来使用。来使用。函数返回值函数返回值为为引用类型引用类型表示该函数返回值是一个表示该函数返回