语法:类型 &函数名(形参列表){ 函数体 }ios
特别注意:安全
1.引用做为函数的返回值时,必须在定义函数时在函数名前将&ide
2.用引用做函数的返回值的最大的好处是在内存中不产生返回值的副本函数
//代码来源:RUNOOB #include<iostream> using namespace std; float temp; float fn1(float r){ temp=r*r*3.14; return temp; } float &fn2(float r){ //&说明返回的是temp的引用,换句话说就是返回temp自己 temp=r*r*3.14; return temp; } int main(){ float a=fn1(5.0); //case 1:返回值 //float &b=fn1(5.0); //case 2:用函数的返回值做为引用的初始化值 [Error] invalid initialization of non-const reference of type 'float&' from an rvalue of type 'float' //(有些编译器能够成功编译该语句,但会给出一个warning) float c=fn2(5.0);//case 3:返回引用 float &d=fn2(5.0);//case 4:用函数返回的引用做为新引用的初始化值 cout<<a<<endl;//78.5 //cout<<b<<endl;//78.5 cout<<c<<endl;//78.5 cout<<d<<endl;//78.5 return 0; }
case 1:用返回值方式调用函数(以下图,图片来源:伯乐在线):spa
返回全局变量temp的值时,C++会在内存中建立临时变量并将temp的值拷贝给该临时变量。当返回到主函数main后,赋值语句a=fn1(5.0)会把临时变量的值再拷贝给变量a指针
case 2:用函数的返回值初始化引用的方式调用函数(以下图,图片来源:伯乐在线)code
这种状况下,函数fn1()是以值方式返回到,返回时,首先拷贝temp的值给临时变量。返回到主函数后,用临时变量来初始化引用变量b,使得b成为该临时变量到的别名。因为临时变量的做用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束,也就是在语句float &b=fn1(5.0);以后) ,因此b面临无效的危险,颇有可能之后的值是个没法肯定的值。对象
若是真的但愿用函数的返回值来初始化一个引用,应当先建立一个变量,将函数的返回值赋给这个变量,而后再用该变量来初始化引用:继承
int x=fn1(5.0); int &b=x;
case 3:用返回引用的方式调用函数(以下图,图片来源:伯乐在线)生命周期
这种状况下,函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数,即主函数的赋值语句中的左值是直接从变量temp中拷贝而来(也就是说c只是变量temp的一个拷贝而非别名) ,这样就避免了临时变量的产生。尤为当变量temp是一个用户自定义的类的对象时,这样还避免了调用类中的拷贝构造函数在内存中建立临时对象的过程,提升了程序的时间和空间的使用效率。
case 4:用函数返回的引用做为新引用的初始化值的方式来调用函数(以下图,图片来源:伯乐在线)
这种状况下,函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数。在主函数中,一个引用声明d用该返回值初始化,也就是说此时d成为变量temp的别名。因为temp是全局变量,因此在d的有效期内temp始终保持有效,故这种作法是安全的。
3.不能返回局部变量的引用。如上面的例子,若是temp是局部变量,那么它会在函数返回后被销毁,此时对temp的引用就会成为“无所指”的引用,程序会进入未知状态。
4.不能返回函数内部经过new分配的内存的引用。虽然不存在局部变量的被动销毁问题,但若是被返回的函数的引用只是做为一个临时变量出现,而没有将其赋值给一个实际的变量,那么就可能形成这个引用所指向的空间(有new分配)没法释放的状况(因为没有具体的变量名,故没法用delete手动释放该内存),从而形成内存泄漏。所以应当避免这种状况的发生
5当返回类成员的引用时,最好是const引用。这样能够避免在无心的状况下破坏该类的成员。
6.能够用函数返回的引用做为赋值表达式中的左值
#include<iostream> using namespace std; int value[10]; int error=-1; int &func(int n){ if(n>=0&&n<=9) return value[n];//返回的引用所绑定的变量必定是全局变量,不能是函数中定义的局部变量 else return error; } int main(){ func(0)=10; func(4)=12; cout<<value[0]<<endl; cout<<value[4]<<endl; return 0; }
运行结果
10 12
D.用引用实现多态
在C++中,引用是除了指针外另外一个能够产生多态效果的手段。也就是说一个基类的引用能够用来绑定其派生类的实例
class Father;//基类(父类) class Son:public Father{.....}//Son是Father的派生类 Son son;//son是类Son的一个实例 Father &ptr=son;//用派生类的对象初始化基类对象的使用
特别注意:
ptr只能用来访问派生类对象中从基类继承下来的成员。若是基类(类Father)中定义的有虚函数,那么就能够经过在派生类(类Son)中重写这个虚函数来实现类的多态。