引用
引用是个别名,当建立引用时,程序用另一个变量或对象的名字初始化它,从那时起,引用就作为目标的别名而使用,对引用的改动就相当于对目标的改动。
要建立一个引用,需要在目标类型后面接上引用运算符“&”,然后是引用名(可以使用任何合法的变量名)。
例如
int number;
int& oneInt = number;//此时oneInt就相当于number变量,对oneInt操作就相当于对number操作。
注意,引用不是一个变量,它不会占用内存空间,引用声明时也不会改变目标的状态,引用只有声明,没有定义。其次,引用在声明时必须进行初始化,否则编译报错,引用运算符“&”仅在声明的时候使用,其他情况直接使用引用名即可。
引用的声明与指针类似,以下三种声明等价。
int& rInt;
int &rInt;
int & rInt;
引用的操作
//..
int main() {
int intOne = 5;
int& rInt = intOne;
std::cout<<"intOne:"<<intOne<<endl;
std::cout<<"rInt:"<<rInt<< endl;
std::cout<<"&rInt == &intOne:"<<&rInt<<endl;//C++不提供访问引用本身地址的方法,因为其没有任何意义,故这里的地址和目标本身intOne的地址相同。
return 0;
}
运行结果:
intOne:5
rInt:5
&rInt == &intOne:00F3:5300
引用一旦初始化,它就维系在一定的目标上,永远与之绑定,如
int intOne=5;
int& rInt=intOne;
int intTwo=10;
rInt=intTwo;
rInt=8;
cout<<intOne<<","<<intTwo<<endl;//输出8,10
以上代码中,引用 rInt 被重新赋值为 intTwo,但从控制台输出看,引用的绑定关系并没有改变,我们操作 rInt 仍然相当于在对 intOne 进行操作,而不是 intTwo,引用 rInt 的地址仍然与 intOne 一致。
什么可以被引用
可以对变量,指针,对象等进行引用,不能对 void 类型进行引用,也不能对数组进行引用。
void 在语法上相当于一种类型,但本质上并不是一个实际的类型,因为这种类型没有意义,没有任何一个变量或对象的类型是 void,当然也就失去的引用的意义。
我们学习过 C 语言将知道,数组名本质是数组的首地址,是一个 const 型的指针,如果我们要对一个数组进行引用,那么将意味着数组中的每一个元素都要初始化为其他的内存实体,显然不现实;另一方面,数组名代表的是整个数组空间的起始地址,如果对其引用,那将和指向数组的指针没有多少区别。
以下均为错误行为
void& a=3; //error
int a[10];
int& ra[10]=a; //error
int num=5;
int&& rNum=num;//error无引用的引用,二级引用?
int& *p= &num ;//error无引用的指针
int& r= null;//无意义
int& ri=int;//引用是对变量或对象的引用,而不是对一种类型的引用
用引用传参
以前我们想通过函数对变量进行处理,但我们发现,变量(实参)传入函数后,函数会将实参赋值给形参,然后对形参进行函数操作,最终我们的实参被原封不动的“还了回来”,之前我们通常用变量的指针进行处理,而现在我们多了一种手段:引用
void swap(int& a,int& b)
{
int temp=a;
a=b;
b=temp;
}
int main(){
int x=5,y=10;
cout<<"before:"<<x<<","<<y<<endl;//输出before:5,10
swap(x,y);
cout<<"after:"<<x<<","<<y<<endl;//输出before:10,5
return 0;
}
引用具有指针的特性,但在调用引用传递的函数时,可读性比指针传递更好,简单清晰。
函数返回多个值
众所周知,函数只能返回一个值,如果需要返回多个值该怎么办?解决办法之一就是用引用给函数传递你需要返回的参数,以下程序片段实现了函数返回多值
bool Factor(int,int&,int&);
int main(){
//..
Factor(num,Squared,Cubed);//Squared和Cubed即为函数返回的另外两个值
//..输出Squared和Cubed
//..
}
bool Factor(int n,int& rSquared,int& rCubed){
if(n>20||n<0)
return true;
rSquared =n*n;
rCubed=n*n*n;
return false;
}
程序需要的 Squared 和 Cubed 是通过改变传递给函数的引用 rSquared 和 rCubed 返回的,而没有使用函数本身返回的 bool 值。
用引用返回值
函数返回值时,需要生成一个值的副本;用引用返回值时,不生成副本。
float func1(float r){
//..
}
float& func2(float r){
//..
}
int main(){
float a=func1(5.0);
float& b=func2(5.0);
float c=fun2(5.0);
//..
}
调用 func1 时,函数返回值先经过栈区的临时变量,在传递给 main 函数中的变量 a;b 调用 func2 时,函数返回值直接作为引用 b 的初始化,不经过栈区创建临时变量,c 调用 func2 时,直接将函数返回值传递给 c 变量,不经过栈区临时变量。
func2 ()函数返回一个引用,因此不产生任何返回值的副本,当然,这个返回值需要使用全局变量或静态变量,避免函数结束后,该变量被释放。
略...
函数作为可修改的左值*
思路:让函数返回一个引用(通过引用传入函数,或全局变量等...)然后就可以对函数所返回的引用进行操作了,此时函数即为一个可修改的左值。
const 限定引用?
C++ 不区分变量的 const 引用和 const 变量的引用,程序不能给引用本身重新赋值,前面我们已经提到,因此引用总是 const,如果对引用进行 const 那么等价于使所引用的对象成为 const 型变量。
以下为错误的引用声明
const double const& a=1;//error
编辑:Henry 2021-03-03 未授权禁止转载
版权属于:字节星球/肥柴之家 (转载请联系作者授权)
原文链接:https://www.bytecho.net/archives/1707.html
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。