引用
- 定义:引用可以理解成给变量多起了一个别名。
- 格式:类型 & 引用变量名=原变量名
比如
int a=10;
int &b=a;
b=20;
定义变量a的值为10,又定义一个变量b作为a的别名,这是a和b表示同一块儿空间的值,改变b的值为20,a的值也改变。
引用的特点
(1)一个变量可以有多个别名
(2)引用必须要初始化
(3)引用只能在初始化的时候改变一次,之后不能再做修改。当引用作为参数时
(1)值传递:如果使用 非引用的方式 进行传值,则生成临时变量接收实参的值
void fun(int a,int b){
;
}
void test{
fun (a,b);
}
和c语言函数中一样,如果不传实参的地址,则函数中的形参是实参的一份临时拷贝,值相同,
但是是不同的变量,且函数的调用结束后,随栈帧一并销毁。
(2)用引用传递
void fun(int &a,int &b)
和c语言函数中传地址意义相同,函数中改变a和b,会对实参造成影响
(3)当不希望函数内改变参数的值时,尽量使用常引用传参
void fun(const int &a)
这里就保护了a在函数fun中不变。
- 传值做返回值&传引用作为返回值
int add(int a,int b)
{
int ret=a+b;
return ret;
}
int main()
{
int a=add(1,2);
add(10,20);
cout<<a<<endl;
}
上述代码中输出的a的值是3。
int &add(int a,int b)
{
int ret=a+b;
return ret;
}
int main()
{
int &a=add(1,2);
add(10,20);
cout<<a<<endl;
上述代码输出的a的值是30.
这是怎么回事?
第一段代码中,,add(1,2)得出结果ret=3,ret在传递回main函数时,生成一份临时变量,a接收的就是这份临时变量的值。之后的代码再跟a没有关系。
第二段中函数的返回值类型是 int& ,这说明返回值是ret的别名,跳过了临时变量的生成。当add(10,20)函数开始调用时,将生成相应的栈帧,因为函数相同,栈帧与add(1,2)时没有变化,ret也在原来add(1,2)的位置由3改成了30。而a又是ret的别名,所以a的值也被修改成了30。
结论:
1.不要返回一个临时变量的引用(因为在之后的函数调用中,该临时变量所在的空间可能会分配给别的栈帧,并被使用并赋值)
2.如果返回对象出了当前函数的作用域后仍然存在(比如静态变量),则最好用引用返回(这样就少了一次临时拷贝,更高效)引用和指针的区别和联系
1.引用只能在定义时初始化一次,之后不能修改,而指针可以任意修改
2.引用不能为空,指针可以为空
3.sizeof(引用名)所得是引用的变量本身的大小,sizeof(指针名)是对象地址的大小
4.指针和引用的增减意义不同
5.引用更安全,指针有空指针和野指针的存在,相对讲不太安全。
const
const关键字能保护修饰的对象只能被读取,不能被修改。
在这里着重讲一下const 修饰指针和引用时要注意的问题。
1 const int *p;
2 int const *p;
3 int* const p;
4 const int* const p;
首先要分清const 位于不同位置时修饰的含义(假设p指向变量a):
当const位于*之前,修饰的是*p,(即变量a的值是只读的)
当const位于*之后,修饰的是p变量本身,(变量p内存储的是a的地址,p只读意思就是只能存a地址,不能再存别的变量的地址(比如b))。
理清这一点后来看一下代码:
int a=10;
(1)
const int* p1=&a; //错误
int *p2=p1;
(2)
int const*p1=&a; //错误
int *p2=p1;
(3)
int* const p1=&a; //正确
int *p2=p1;
(4)
const int a=10; //错误
int &b=a;
(5)
const int a=10; //正确
int b=a;
(1)中const修饰 *p1, *p1只读,而p2也指向a, *p2的改变会影响 *p1,所以错误。
(2)与(1)相同
(3)中const修饰的是p1本身,p1只读,而p2也指向a,p2的改变不会影响p1,所以正确。
(4)中const修饰的是a,a只读,b作为a的别名,修改b也会影响a,所以错误。
(5)中const修饰的是a,把a的值赋给b,a和b是不同的两个变量,互不影响,所以正确。
根据以上的分析能得出一个结论:
在指针和引用前加const,一定要注意后面的代码不能使访问的权利扩大
比如 :
只读–>可读可写
以下权限缩小,不变都是可行的:
可读可写–>可读可写
可读–>可读
可读可写–>可读