引用仅仅给原变量起别名,和原变量是同一个东西,一个东西的两个名字。
关于引用
int a=2;
int &b=a;
b=56; // b是 a的一个别名, b 和 a 的地址是一样的
声明一个引用时,必须同时使之初始化
int &r; // 不合法
int &r = a; // 合法
引用在初始化之后不可修改
int &r = a; // 初始化, r 是 a 的引用
int b = 885;
r = b; // 只是赋值操作,不是更改引用
常引用
const int &z=x; // z不能做左值, 即 z=32; 这样的事情是不被允许的
引用只能引用变量,不能引用常量和表达式。
数组名是数组首元素的地址,本身不是一个占有存储空间的变量
char c[6]="hello";
char &rc=c; // error
指针变量的引用
int i=5;
int *p=&i;
int * &pt=p; // 建立指针变量 p的引用 pt
pt代表一个int *类型的数据对象(即指针变量)
数组的引用
int a[10];
int (&b)[10] = a;
b 和 a 等价
函数参数:传引用 和 传指针 的区别
传指针
void swap(int* p1,int* p2){
int* temp=p1;
p1=p2;
p2=temp;
}
int main(){
int a=1,b=3;
int *p1=&a,*p2=&b;
swap(p1,p2);
}
- 在
swap函数
中 p1和p2 确实交换了指向 ,但swap函数
中的 p1 p2 与main函数
中的 p1 p2 不是同一个 。 - 因为此时有四个变量,main中两个(p1,p2),swap中两个(p1,p2)。
swap函数
的p1指向其他地方时,和main函数
中的p1没有任何关系。
传引用
void swap(int* &p1,int* &p2){
int* temp=p1;
p1=p2;
p2=temp;
}
- 此时
swap函数
中的 p1 p2是外面的别名,只不过名字一样,和外面是同一个东西。
void f(int &x);
f(y); // 在 f 里面对 x做任何的修改, 外面的 y 就变了。
做返回值
用引用做返回值的最大好处是,在内存中不产生被返回值的副本,速度快。
// 不能返回局部变量的引用
int & test01(){
int a=10; // 将 a改为静态变量是可以的 static int a=10;
return a;
}
引用做右值的例子
float temp; // 全局变量
float &fn2(float r){ // &说明返回的是temp的引用,换句话说就是返回temp本身
temp=r*r*3.14;
return temp;
}
float c=fn2(5.0); // 相当于执行 float c=temp; c和 temp只是值一样,他们是两个变量 c并不是 temp的别名。
float &d=fn2(5.0); // 相当于执行 float &d=temp; 此时 d成为变量 temp的别名。 修改 d, temp随之变化。
引用做左值的例子
int arrs[5]={12,13,14,15,16};
int &setValues(int i){
return arrs[i]; 函数返回 arrs[i]的引用,也可以理解为 arrs[i]本身
}
int main(){
cout<<"更改前:"<<endl;
for(int i=0;i<5;i++){
cout<<"arrs["<<i<<"]:"<<arrs[i]<<endl;
}
setValues(1)=12345; // 实质是 arrs[1]=12345;
setValues(3)=547395; // 实质是 arrs[3]=547395;
cout<<"更改后:"<<endl;
for(int i=0;i<5;i++){
cout<<"arrs["<<i<<"]:"<<arrs[i]<<endl;
}
}
引用的本质
本质是指针常量。
int &ref=a; // 编译器自动转换为 int *const ref =&a;
ref=20; // 当我们在做这件事情的时候, 编译器自动帮我们转换为 *ref=20;
Attention
非 const 的引用 不能绑定:临时对象,字面常量,const常变量
[Error] invalid initialization of non-const reference of type 'Complex&' from an rvalue of type 'Complex'
[Error] cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'|
int i;
void func(int &n);
for(i=1;i<=6;i++){
func(i*4); // wrong
}
i*4 只是一个临时变量。
可以改为 void func(const int &n);
常引用
const int & b;
所引用的对象不会被更新,并且b可以绑定到一个常对象
对于基本数据类型的引用,不能修改该数据的值
对于类类型的引用,不能修改它的数据成员,也不可以调用它的非 const 的成员函数。
常引用经常拿来做形参
参考:
C/C++ 引用作为函数的返回值
C++ 引用 reference
值传递 (pass by value),指针传递(pass by pointer),当发生函数调用时,需要给形参分配存储单元、当传递是对象时,要调用拷贝构造函数。
而且指针最后析构时,要处理内存释放问题。
引用传递(pass by refenrence),在内存中没有产生形参。效率大大提高!也不用处理指针的析构问题。
在形参中数据较为复杂时(比如以对象作为参数),应该尽量使用引用,少利用指针与值传递。