c++常见面试题30道
- 格式:doc
- 大小:66.50 KB
- 文档页数:16
以下是一些可能有用的C软件工程师面试题目:
1.什么是C语言?C语言有哪些特点?
2.什么是内存对齐?请简述内存对齐规则。
3.请解释指针和引用的区别。
4.请解释堆栈和堆的区别。
5.请解释虚函数和多态机制的实现方式。
6.如何判断一段程序是由C编译器还是C++编译器编译的?
7.对于一个频繁使用的短小函数,在C语言中如何实现?在C++中如何实现?
8.请解释sizeof运算符的作用和用法。
9.什么是哈希表?哈希表有哪些常见的操作?
10.请解释STL中unordered_map和map的区别。
11.请解释二叉树、平衡二叉树和AVL树的区别。
12.请解释链表、栈和队列的特点和应用场景。
13.请解释回溯算法的思想和应用。
14.请解释动态规划算法的思想和应用。
15.请解释递归算法的思想和应用。
16.如何测试和调试C语言程序?
17.在C语言中如何处理文件?
18.在C语言中如何实现多线程编程?
19.如何优化C语言程序的性能?
20.你如何解决常见的C语言编程问题?请给出一些实例。
c语言面试经常问的问题C语言面试题C语言面试题篇11、已知字母b的ASCII码的十进制代码为98,则执行下列语句输出为(C)ch=’b’;ch–;printf(%d,%c\n”,ch,ch);A)a,bB)运算不合法,故有语法错C)97,aD)格式描述和输出项不匹配,输出无值2、若变量a已说明为float类型,则能实现将a中的数值保留小数点后两位,第三位进行四舍五入运算的表达式是(C)A)a=(a某100+0.5)/100.0B)a=(a某100+0.5)/100C)a=(int)(a某100+0.5)/100D)a=(a/100+0.5)某100.03、下列程序段的输出结果是(B)inta=5,b=7;printf(“%d,%d”,a++,++b);A)5,7B)5,8C)6,7D)6,8C语言面试题篇21、下列程序的输出结果是(D){inta=4;a某=a+=6;printf(“%d\n”,a);}A)40B)60C)80D)1002、下列程序的输出结果是(C)main(){inta=8;printf(“%a”,(a=a某5,a+6));}A)14B)40C)46D)50C语言面试题篇31、定义a为整型,下列表达式a=3>6的运行后,a的值为(A)A)0B)1C)3D)表达式错误2、、如果a=1,b=2,c=3,d=4,则条件表达式a>ba:c>dc:d的值为(D)A)1B)2C)3D)43、下述程序段的输出结果是(A){inta=5;printf(“%d,”,a);a+=a某=a-=a某=2;printf(“%d”,a);}A)5,0B)0,0C)5,12D)0,124、下列变量名中合法的是(A)A)TomB)3a6bC)6a7bD)5ABC5、对于条件表达式(M)(a++):(a–),其中的表达式M等价于(C)A)M==0B)M==1C)M!=0D)m!=1。
c语言编程面试题目及答案C语言是一种广泛应用于计算机编程领域的编程语言,掌握好C语言编程知识对于求职和面试来说至关重要。
本文将提供一些常见的C语言编程面试题目及其相应的答案,以帮助读者更好地准备面试。
1. 请解释一下C语言的优点和缺点。
答:C语言的优点包括高效性、可移植性、功能丰富、灵活性强、易于学习和使用等。
同时,由于它是一种较底层的语言,可以更好地控制硬件和内存,适用于开发系统软件和嵌入式系统。
然而,C语言也存在一些缺点,比如相对较低的抽象层级、易于出错、不支持面向对象等。
此外,由于C语言没有内置的异常处理机制,错误处理需要手动处理。
2. 请解释什么是指针,并描述它的作用。
答:指针是C语言中一种特殊的数据类型,用于存储变量的内存地址。
通过指针,可以直接访问和修改指向内存位置的值,这对于实现动态内存分配、传递大量数据和操作复杂数据结构非常有用。
3. 请解释C语言中的数组和指针之间的关系。
答:数组和指针在C语言中有着密切的关系。
实际上,数组名可以被看作是一个指向数组第一个元素的指针。
通过指针算术运算,可以访问数组中的每个元素。
此外,数组参数在函数调用时会被自动转换为指针。
4. 请解释什么是函数指针,并说明它的用途。
答:函数指针是指向函数的指针变量。
通过函数指针,可以动态地选择调用不同的函数,实现代码的灵活性和重用性。
函数指针常用于回调函数、实现多态等场景。
5. 请解释C语言中的动态内存分配,并说明如何使用相关函数。
答:动态内存分配是指在程序运行时根据需要动态申请和释放内存。
C语言提供了动态内存分配相关的函数malloc、calloc和realloc,它们分别用于申请内存、申请带初始化的内存和重新分配内存。
使用这些函数时需要注意及时释放已申请的内存,以免造成内存泄漏。
6. 请解释C语言中的结构体,并举例说明其用法。
答:结构体是一种自定义的复合数据类型,可以包含多个不同类型的成员变量。
通过结构体,可以将相关数据组织在一起,方便进行管理和操作。
c面试试题及答案一、自我介绍你好,我是XXX,很高兴有机会参加C面试。
我具备扎实的编程基础和丰富的项目经验,在此次面试中,我将展示我的能力和潜力。
谢谢!二、C语言基础知识1. 请解释C语言中的指针(pointer)是什么?指针是一种变量,它存储了内存地址。
通过指针,我们可以直接访问和修改内存中的数据。
指针的灵活性使得我们可以在C语言中进行高效的内存管理和操作。
2. 请描述C语言中的动态内存分配的过程及对应的函数。
动态内存分配是在程序运行时按需分配和释放内存的过程。
在C语言中,使用malloc函数动态分配内存,使用free函数释放已分配的内存。
具体分配内存的大小和释放内存的时机需要根据具体需求来决定。
3. 什么是结构体(struct)?如何定义和使用结构体?结构体是一种自定义的数据类型,它可以将不同类型的数据按照一定的组织方式打包在一起。
在C语言中,我们可以使用struct关键字定义结构体,并通过点操作符(.)来访问结构体成员。
4. C语言中的位运算符有哪些,分别用于什么场景?C语言中常用的位运算符有按位与(&)、按位或(|)、按位异或(^),它们用于对二进制数进行位级操作。
位运算可以在一些特定场景中提高程序的运行效率,如位掩码、位标记等。
三、编程题请编写一个C语言程序,实现冒泡排序算法。
```c#include <stdio.h>void bubbleSort(int arr[], int size) {int i, j, temp;for (i = 0; i < size - 1; i++) {for (j = 0; j < size - i - 1; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}int main() {int arr[] = {5, 2, 9, 3, 7};int size = sizeof(arr) / sizeof(arr[0]);bubbleSort(arr, size);printf("排序结果:");for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}return 0;}```这个程序实现了冒泡排序算法,将数组中的元素按照升序排列,并输出排序结果。
c的面试题及答案面试题一:请解释一下C语言的指针和引用的区别。
答案:在C语言中,指针和引用都是用来处理内存地址的。
它们的主要区别在于以下几个方面:1. 定义和使用方式:- 指针是一个变量,存储的是一个内存地址。
通过使用"*"操作符可以获取或修改该地址对应的值。
- 引用则是一个已存在对象的别名。
它在定义时需要和原对象进行绑定,并且无法更改绑定的对象。
2. 空指针和无效引用:- 指针可以被赋值为空指针(NULL)或无效的地址值,表示指针不指向任何有效的内存地址。
- 引用必须在定义时进行初始化,并且必须引用一个有效的对象。
3. 内存管理:- 指针需要显式地通过动态内存分配函数(如malloc())进行内存的分配和释放。
- 引用的内存管理则由编译器自动处理,无需手动管理。
4. 数组和函数的传递:- 指针可以用于处理数组或者作为函数的参数进行传递。
- 引用可以作为函数参数,但无法直接用于处理数组。
面试题二:请解释C语言中的堆和栈的区别。
答案:在C语言中,堆和栈是两种不同的内存分配方式,具有以下区别:1. 分配方式:- 栈是由编译器自动分配和释放的,它的空间有限,大小在编译时就已经确定。
- 堆是由程序员手动分配和释放的,它的空间相比栈更大,并且大小在运行时可动态调整。
2. 内存结构:- 栈的数据结构为“先进后出”的方式,即后进栈的数据先出栈。
- 堆则没有明确的数据结构,按照动态分配顺序分配内存。
3. 分配效率:- 栈的分配和释放速度要快于堆,因为栈只需要移动栈顶指针即可。
- 堆的分配和释放速度相对较慢,因为需要在运行时进行内存的动态分配和回收。
4. 使用方式:- 栈主要用于存储局部变量、函数调用和函数参数等数据。
- 堆主要用于存储动态分配的内存,如通过malloc()函数分配的内存块。
面试题三:请解释C语言中的宏定义和常量的区别。
答案:在C语言中,宏定义和常量都可以用来表示不可更改的值,但它们的区别如下:1. 定义方式:- 宏定义使用“#define”关键字进行定义,没有数据类型限制。
应届生c语言面试题
以下是一些可能的应届生C语言面试题:
1. C语言有哪些数据类型?
2. C语言中如何定义变量?
3. C语言中什么是常量?
4. 什么是函数?如何定义一个函数?
5. 函数的返回值是什么?
6. 什么是传值调用和传址调用?
7. 什么是数组?如何定义一个数组?
8. 什么是字符串?如何定义一个字符串?
9. 什么是结构体?如何定义一个结构体?
10. 什么是联合体?如何定义一个联合体?
11. C语言中的指针是什么?如何声明和使用指针变量?
12. 什么是递归函数?如何实现递归函数?
13. C语言中如何实现文件操作?
14. C语言中如何进行内存管理?
15. C语言中什么是预处理器指令?include和define的作用是什么?
16. C语言中什么是位运算?有哪些位运算符?
17. C语言中什么是条件编译?有哪些条件编译指令?
18. C语言中什么是枚举类型?如何定义枚举类型?
19. C语言中什么是强制类型转换?如何进行强制类型转换?
20. 描述一下C语言的内存布局,包括代码区、数据区和堆区。
以上是一些可能的面试题,当然,具体的面试题目会根据具体的公司和职位而有所不同。
在面试之前,你可以通过查阅相关资料和做练习题来准备这些面试题。
1、关键字 static 的作用是什么?这个简单的问题很少有人能回答完全。
在 C 语言中,关键字static 有三个明显的作用: 1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2).在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。
它是一个本地的全局变量。
3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。
那就是,这个函数被限制在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。
这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
2、.h 头文件中的 ifndef/define/endif 的作用?答:防止该头文件被重复引用。
3、描述实时系统的基本特性答:在特定时间内完成特定的任务,实时性与可靠性。
4、什么是平衡二叉树?答:左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于1。
5、冒泡排序算法的时间复杂度是什么?答:O(n^2)6、队列和栈有什么区别?答:队列先进先出,栈后进先出7、局部变量能否和全局变量重名?答:能,局部会屏蔽全局。
要用全局变量,需要使用"::" 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内8、全局变量可不可以定义在可被多个.C 文件包含的头文件中?为什么?答、可以,在不同的C 文件中以static 形式来声明同名全局变量。
可以在不同的 C 文件中声明同名的全局变量,前提是其中只能有一个 C 文件中对此变量赋初值,此时连接不会出错。
9、do……while 和while……do 有什么区别?答前一个循环一遍再判断,后一个判断以后再循环。
C常用面试题库1.简述private、protected、public、internal修饰符的访问权限。
答.private:私有成员,在类的内部才可以访问。
protected:保护成员,该类内部和继承类中可以访问。
public:公共成员,完全公开,没有访问限制。
internal:在同一命名空间内可以访问。
2.列举页面之间传递值的几种方式。
答.1.使用QueryString,如....id=1;repone.Redirect()....2.使用Seion变量3.使用Server.Tranfer3.一列数的规则如下:1、1、2、3、5、8、13、21、34......求第30位数是多少,用递归算法实现。
答:publicclaMainCla{publictaticvoidMain(){Conole.WriteLine(Foo(30));}publictaticintFoo(inti){if(i<=0)return0;eleif(i>0&&i<=2)return1;elereturnFoo(i-1)+Foo(i-2);}}4.C#中的委托是什么?事件是不是一种委托?答:委托可以把一个方法作为参数代入另一个方法。
委托可以理解为指向一个函数的引用。
是,是一种特殊的委托5.override与重载的区别答:override与重载的区别。
重载是方法的名称相同。
参数或参数类型不同,进行多次重载以适应不同的需要Override是进行基类中函数的重写。
为了适应需要。
6.如果在一个B/S结构的系统中需要传递变量值,但是又不能使用Seion、Cookie、Application,您有几种方法进行处理?答:thi.Server.Tranfer7.请编程遍历页面上所有Te某tBo某控件并给它赋值为tring.Empty?答:foreach(Sytem.Window.Form.Controlcontrolinthi.Control){if(controliSytem.Window.Form.Te某tBo某){Sytem.Window.Form.Te某tBo某tb=(Sytem.Window.Form.Te某tBo 某)control;tb.Te某t=String.Empty;}}8.请编程实现一个冒泡排序算法?答:int[]array=newint;inttemp=0;for(inti=0;i<array.Length-1;i++){for(intj=i+1;j<array.Length;j++){if(array[j]<array){temp=array;array=array[j];array[j]=temp;}}}9.描述一下C#中索引器的实现过程,是否只能根据数字进行索引?答:不是。
精选全文完整版(可编辑修改)c语言面试题目及最佳答案1、描述⼀下gcc的编译过程?gcc编译过程分为4个阶段:预处理、编译、汇编、链接。
预处理:头⼀件包含、宏替换、条件编译、删除注释编译:主要进⼀词法、语法、语义分析等,检查⼀误后将预处理好的⼀件编译成汇编⼀件。
汇编:将汇编⼀件转换成⼀进制⼀标⼀件链接:将项⼀中的各个⼀进制⼀件+所需的库+启动代码链接成可执⼀⼀件2、内存的最⼀存储单位以及内存的最⼀计量单位分别是?内存的最⼀存储单位为⼀进制位,内存的最⼀计量单位字节3、#include<> 与#include ""的区别?include<>到系统指定⼀录寻找头⼀件,#include ""先到项⼀所在⼀录寻找头⼀件,如果没有找再到系统指定的⼀录下寻找4、描述⼀下变量的命名规则变量名有字⼀、数值、下划线组成,但不能以数值开头5、变量的声明与定义有啥区别?声明变量不需要建⼀存储空间,变量的定义需要建⼀存储空间6、谈谈c语⼀中有符号和⼀符号的区别?有符号:数据的最⼀位为符号位,0表示正数,1表示负数⼀符号:数据的最⼀位不是符号位,⼀是数据的⼀部分7、谈谈计算机中补码的意义统⼀了零的编码将符号位与其他位统⼀处理将减法运算转换成加法运算8、谈谈数组的特点同⼀个数组所有的成员都是相同的数据类型,同时所有的成员在内存中的地址是连续的9、数组的分类数组的分类主要是:静态数组、动态数组两类。
静态数组:类似int arr[5];在程序运⼀就确定了数组的⼀⼀,运⼀过程不能更改数组的⼀⼀。
动态数组:主要是在堆区申请的空间,数组的⼀⼀是在程序运⼀过程中确定,可以更改数组的⼀⼀。
10、描述⼀下⼀维数组的不初始化、部分初始化、完全初始化的不同点不初始化:如果是局部数组数组元素的内容随机如果是全局数组,数组的元素内容为0 部分初始化:未被初始化的部分⼀动补0完全初始化:如果⼀个数组全部初始化可以省略元素的个数数组的⼀⼀由初始化的个数确定11、谈谈数组名作为类型、作为地址、对数组名取地址的区别?数组名作为类型:代表的是整个数组的⼀⼀数组名作为地址:代表的是数组⼀元素的地址对数组名取地址:代表的是数组的⼀地址12、谈谈你对⼀维数组在物理上以及逻辑上的数组维度理解⼀维数组在逻辑上是⼀维的,在物理上是⼀维的13、描述⼀下函数的定义与函数的声明的区别函数定义:是指对函数功能的确⼀,包括指定函数名、函数类型、形参及其类型、函数体等,它是⼀个完整的、独⼀的函数单位。
c语言面试题目100及最佳答案1. 介绍C语言的基本数据类型和其范围。
C语言的基本数据类型有char、int、float和double。
它们的范围分别如下:- char: -128到127- int: -32768到32767- float: 3.4e-38到3.4e+38- double: 1.7e-308到1.7e+3082. 什么是指针(Pointer)?请解释指针的作用。
指针是一个变量,其值为另一个变量的地址。
它的作用是用于在程序中动态地分配内存、传递函数参数和实现复杂数据结构,如链表和树。
3. 请解释C语言中的自动变量和静态变量的区别。
自动变量是在函数内部声明的变量,在函数结束时会被销毁。
而静态变量是在函数内或函数外声明的变量,它的值在函数调用之间保持不变。
4. 解释什么是递归函数?递归函数是一个可以调用自身的函数。
在递归函数中,函数会反复调用自己,直到满足终止条件为止。
5. 请解释C语言中的位运算符。
C语言中的位运算符包括与(&)、或(|)、异或(^)、取反(~)、左移(<<)和右移(>>)运算符。
这些运算符用于对二进制数的位进行操作,常用于位掩码和位操作等场景。
6. 什么是结构体?结构体是一种用户自定义的数据类型,它可以包含不同类型的数据成员。
通过结构体,我们可以将多个不同的变量组合在一起,形成一个逻辑上的整体。
7. 解释C语言中的动态内存分配。
动态内存分配是指在程序运行时根据需要动态地分配内存空间。
C 语言中的动态内存分配函数包括malloc、calloc和realloc,通过这些函数可以在程序运行时根据需求分配或释放内存。
8. 请解释C语言中的头文件和库文件的作用。
头文件包含一组函数声明、宏定义和结构体声明等信息,用于在源文件中引用。
库文件则包含已编译的函数实现和数据,通过链接库文件可以在程序中使用这些函数和数据。
9. 什么是指针数组和数组指针?指针数组是一个数组,每个元素都是指针类型。
1.new、delete、malloc、free关系delete会调用对象的析构函数,和new对应free只会释放内存,new调用构造函数。
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。
对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。
注意new/delete不是库函数。
2.delete与delete []区别delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。
在More Effective C++中有更为详细的解释:“当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存。
”delete 与new配套,delete []与new []配套MemTest *mTest1=new MemTest[10];MemTest *mTest2=new MemTest;Int *pInt1=new int [10];Int *pInt2=new int;delete[]pInt1; //-1-delete[]pInt2; //-2-delete[]mTest1;//-3-delete[]mTest2;//-4-在-4-处报错。
这就说明:对于内建简单数据类型,delete和delete[]功能是相同的。
对于自定义的复杂数据类型,delete和delete[]不能互用。
delete[]删除一个数组,delete删除一个指针。
简单来说,用new分配的内存用delete删除;用new[]分配的内存用delete[]删除。
delete[]会调用数组元素的析构函数。
内部数据类型没有析构函数,所以问题不大。
如果你在用delete时没用括号,delete就会认为指向的是单个对象,否则,它就会认为指向的是一个数组。
3.C++有哪些性质(面向对象特点)封装,继承和多态。
4.子类析构时要调用父类的析构函数吗?析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候,派生类的信息已经全部销毁了。
定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数;析构的时候恰好相反:先调用派生类的析构函数、然后调用基类的析构函数。
5.多态,虚函数,纯虚函数多态:是对于不同对象接收相同消息时产生不同的动作。
C++的多态性具体体现在运行和编译两个方面:在程序运行时的多态性通过继承和虚函数来体现;在程序编译时多态性体现在函数和运算符的重载上;虚函数:在基类中冠以关键字virtual 的成员函数。
它提供了一种接口界面。
允许在派生类中对基类的虚函数重新定义。
纯虚函数的作用:在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行定义。
作为接口而存在纯虚函数不具备函数的功能,一般不能直接被调用。
从基类继承来的纯虚函数,在派生类中仍是虚函数。
如果一个类中至少有一个纯虚函数,那么这个类被称为抽象类(abstract class)。
抽象类中不仅包括纯虚函数,也可包括虚函数。
抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。
但仍可使用指向抽象类的指针支持运行时多态性。
6.求下面函数的返回值(微软)int func(x){int countx = 0;while(x){countx ++;x = x&(x-1);}return countx;}假定x = 9999。
答案:8思路:将x转化为2进制,看含有的1的个数。
7.什么是“引用”?申明和使用“引用”要注意哪些问题?答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。
申明一个引用的时候,切记要对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。
不能建立数组的引用。
8.将“引用”作为函数参数有哪些特点?(1)传递引用给函数与传递指针的效果是一样的。
这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。
因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。
而引用更容易使用,更清晰。
9.在什么时候需要使用“常引用”?如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。
常引用声明方式:const 类型标识符&引用名=目标变量名;例1int a ;const int &ra=a;ra=1; //错误a=1; //正确例2string foo( );void bar(string & s);那么下面的表达式将是非法的:bar(foo( ));bar("hello world");原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。
因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。
引用型参数应该在能被定义为const的情况下,尽量定义为const 。
10.将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?格式:类型标识符&函数名(形参列表及类型说明){ //函数体}好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。
因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!注意事项:(1)不能返回局部变量的引用。
这条可以参照Effective C++[1]的Item 31。
主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。
这条可以参照Effective C++[1]的Item 31。
虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。
例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
(3)可以返回类成员的引用,但最好是const。
这条原则可以参照Effective C++[1]的Item 30。
主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。
如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
(4)流操作符重载返回值申明为“引用”的作用:流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl;因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。
可选的其它方案包括:返回一个流对象和返回一个流对象指针。
但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。
对于返回一个流指针则不能连续使用<<操作符。
因此,返回一个流对象引用是惟一选择。
这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。
赋值操作符=。
这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。
因此引用成了这个操作符的惟一返回值选择。
#include<iostream.h>int &put(int n);int vals[10];int error=-1;void main(){put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10;put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20;cout<<vals[0];cout<<vals[9];}int &put(int n){if (n>=0 && n<=9 ) return vals[n];else { cout<<"subscript error"; return error; }}(5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。
它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。
主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。
根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。
静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。
所以可选的只剩下返回一个对象了。
11、结构与联合有和区别?(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。