1.引用
1.1 引用的概念
C++语言中,可以定义“引用”。引用定义如下:
类型名 & 引用名 = 同类型的某变量名;
例如:int n;
int &r=n;//r就是一个引用,可以说r的类型是int &,r引用了变量n,或者说r成为n的引用。
某个变量的引用和这个变量是一回事,相当于该变量的一个别名。请注意,定义引用时一定要将其初始化,否则编译不会通过,通常会用某个变量去初始化引用,初始化后,它就一直引用该变量,不会再引用别的变量了。也可以用一个引用去初始化另一个引用,这样两个引用就引用同一个变量了。不能用常量初始化引用,也不能用表达式来初始化引用(除非该表达式的返回值是某个变量的引用)。总之,引用只能引用变量。
类型为T &的引用和类型为T的变量是完全兼容的,可以互相赋值。
引用的示例程序如下:
- #include <iostream>
- using namespace std;
- int main()
- {
- int n=4;
- int &r=n; //r引用了n,从此r和n就是一回事
- r = 4; //修改r就是修改n
- cout<<r<<endl; //输出4
- cout<<n<<endl; //输出4
- n = 5; //修改n就是修改r
- cout<<r<<endl; //输出5
- int &r2 = r; //r2和r引用同一个变量n
- cout<<r2<<endl; //输出5
- return 0;
- }
1.2 引用作为函数的返回值
函数的返回值可以是引用,例如下面的程序:
- #include <iostream>
- using namespace std;
- int n = 4;
- int & Setvalue()
- {
- return n; //返回对n的引用
- }
- int main()
- {
- Setvalue()=40; //返回值是引用的函数调用表达式,可以作为左值使用
- cout<<n<<endl; //输出40
- int &r = Setvalue();
- cout<<r<<endl; //输出40
- return 0;
- }
1.3 参数传值
“传值”是指函数的形参是实参的一个拷贝,在函数执行过程中形参的改变不会影响到实参。请看例子:
- #include <iostream>
- using namespace std;
- void Swap(int a,int b)
- {
- int temp;
- temp=a;
- a=b;
- b=temp;
- cout<<a<<b<<endl;
- }
- int main()
- {
- int a=4,b=5;
- Swap(a,b);
- cout<<a<<b<<endl;
- return 0;
- }
上面的程序的输出结果为:
5 4
4 5
说明在Swap函数内部,形参a,b的值的确发生了互换,但是在main中的a,b还是维持原来的值,也就是说形参的改变不会影响实参。
1.4 参数传引用
在传引用的方式下,形参是对应的实参的引用,也就是说,形参和对应的实参是一回事,那么形参的改变就会改变实参的值。例如:
- #include <iostream>
- using namespace std;
- void Swap(int &a,int &b)
- {
- int tmp;
- tmp = a;a = b;b = tmp;
- }
- int main()
- {
- int n1=100,n2=50;
- Swap(n1,n2);
- cout<<n1<<n2<<endl; //输出50 100
- }
进入Swap函数以后,a引用了n1,b引用了n2,a,b的改变会影响到n1,n2的值的改变。
2. 内联函数
使用函数可以减少代码的体积,但是也带来了运行时间的开销,如果一个函数内部的语句非常的少,执行的时间本来就很短,那么调用这个函数的时间就不能忽略,在C++语言中,“inline”很好的解决了函数调用开销的问题。加了“inline”的函数就叫内联函数,例如:
inline int max(int a,int b);
加了inline的作用是相当于在编译的时候将函数的语句代码插入到调用的地方,减少了给变量分配空间后的存取时间,但是inline只是适合短小的函数,对于语句比较多的函数,如果用了inline,相当于付出让体积增加几倍的代价,但是速度只是提高了万分之一,得不偿失,有时候函数看上去很简单,但是包含的循环要用很多次,要消耗大量的时间,也不适合用内联函数。所以内联函数的特点是代码简单,执行很快。
3.函数的重载
C++语言不允许变量重名,但是允许多个函数取相同的名字,只要参数表不同就可以,这称为函数的重载。相当于同一个事物完成不同的功能。
那么在调用同名函数的时候,编译器怎么世道调用哪一个函数呢?很简单,编译器通过函数调用语句中实参的个数和类型来判断。因为重载函数的参数表不同,只要调用函数的语句给出的实参和参数表匹配就调用。例如:
- #include <iostream>
- using namespace std;
- int max(int a,int b)
- {
- cout<<max1<<endl;
- }
- double max(double a,double b)
- {
- cout<<max2<<endl;
- }
- double max(double a,double b,double c)
- {
- cout<<max3<<endl;
- }
- int main()
- {
- max(3,4); //调用int max(int ,int)
- max(2.4,6.0); //调用double max(double ,double)
- max(1.2,3.4,5); //调用double max(double ,double, double)
- max(1,2,3); //调用double max(double ,double, double)
- max(3,1.5); //二义性!!!!!!!
- return 0;
- }
二义性分析:在第21行中,编译器调用int max(int ,int),只要将1.5进行强制的转换即可,调用double max(double , double)也可以,此时编译器不知道调用哪一个函数,因此出现了二义性。
在两个函数同名而且参数个数不同,但是其中参数多的那个函数的参数又可以默认的情况下,也可能发生二义性,例如:
int sum(int a,int b,int c=0);
int sum(int n,int m);
此时调用:
sum(1,2);
此时的编译器不知道是应该以(1,2,0)作为参数调用第一个函数还是以(1,2)调用第二个函数,产生了二义性!