C++之引用怎么用
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++之引用怎么用相关的知识,希望对你有一定的参考价值。
1.引用的概念
引用并不是新定义一个变量,而是给一个已存在的变量取一个别名。编译器并不会为引用变量开辟空间,它和它应用的变量共用一块空间。也就是说引用是同一块变量空间的不同名字。
格式:类型& 引用变量名=引用实体
注意:上面ra的类型还是整形(int),类型并不是int&,对引用进行赋值就是对他引用的实体赋值。
2.引用特性
- 引用在定义时必须初始化。否则不知道引用的哪一个
#include<iostream>
using namespace std;
int main(){
int a=10;
int& ra;//编译时出错
return 0;
}
- 一个变量可以有多个引用。
#include<iostream>
using namespace std;
//这样都是正确的,一块空间的多个命名
int main(){
int a=10;
int& ra=a;
int& rb = a;
int& rc = ra;
return 0;
}
- 应用一旦引用一个实体,再也不能引用其它实体。不然就是赋值。
3.常引用
- 一个常量的引用也应该是一个常量
#include<iostream>
#include<Windows.h>
using namespace std;
int main(){
const int a=10;
//int& ra=a;编译时出错
const int& ra = a;
system("pause");
return 0;
}
原因:变量a是可读不可改写的,引用ra是可读可改写的,如果对ra改写,就会对a产生影响。所以会编译出错。
- 一个变量也可以用一个常量引用来引用
#include<iostream>
#include<Windows.h>
using namespace std;
int main(){
int a=10;
int& ra=a;
const int& rb = a;//可以用一个常量引用
system("pause");
return 0;
}
原因:变量a是可读可改写的,引用rb是可读不可改写的。这是允许的。
- 还有一种特殊情况,当引用时发生隐式转化,用常引用接受可以。如下
#include<iostream>
#include<Windows.h>
using namespace std;
int main(){
double a=3.14;
//int& ra=a;//编译出错
const int& rb = a;//正确
system("pause");
return 0;
}
原因:当发生隐式转化时,会产生一个临时变量,改临时变量先将原来值进行转化,再赋值给新值。重要的原因是,该临时变量具有常量性质(可读不可改写)。所以需要常引用接收。
用上面的例子就是,rb引用a时发生隐式转化,此时会创建一个临时变量tmp,先将a转化为int,再将tmp值赋给rb。
注意是引用的时候发生隐式转化时,提前隐式转化,再引用不需要常引用接收。
#include<iostream>
#include<Windows.h>
using namespace std;
int main(){
double a=3.14;
int c = a;//提前转化,再引用
int& rc = c;//正确
system("pause");
return 0;
}
结论:引用时,读写权限可以缩小不可以放大。
4.使用场景
- 做参数
例如一个简单的交换函数Swap,在C语言中,我们需要进行传址操作,才能实现实参数值的交换,但是在C++中,我们可以使用引用,就可以实现实参的交换。
此时是如何实现交换的呢?
可以这样理解,x是a的引用,y是b的引用,引用就是实体本身,也就是说。x就是a,y就是b,他们发生值交换就是a,b发生值交换。因为这里并没有为x和y开辟空间,形成临时变量。
- 做返回值
这里有几点值得推敲的地方:
1.这里为什么要用static修饰n,如果不用static修饰会怎么样?
上面返回值为int&引用,在main函数中用引用a来接收。我们知道引用并不开辟空间,所以a并没有开辟空间,而是n的引用,也就是n和a的地址会相同。如果不用static修饰n,则n变量在栈上开辟空间,如果调用一个其它的函数,a的值很有可能会发生改变,这样a的值得不到保障。但是static修饰的变量在静态区存储,值并不会发生改变。如下是不用static修饰的变量:
2.返回值不是引用的,如果想用引用来接收,必须使用常引用。
#include<iostream>
#include<Windows.h>
using namespace std;
int Count(){
int n = 0;
n++;
return n;
}
int main(){
//int& a = Count();//编译错误
const int& a = Count();//正确
system("pause");
return 0;
}
原因:和隐式转化差不多,当返回的时候,会生成一个临时变量,该临时变量的值等于返回值。并且,该返回值具有常量性质。
3.引用做返回值,也可以不使用引用来接收,这样值就得到了保障。
原因:此时main函数里的a开辟空间,与n无关了,或者说与返回时创建的临时变量无关了,只是将它的值赋给了a。
也可以看成下面这样。b的改变并不会影响ra,a。
#include<iostream>
#include<Windows.h>
using namespace std;
int& Count(){
int n = 0;
n++;
return n;
}
int main(){
const int a = 10;
const int& ra = a;
int b = ra;//此时b与ra,a无关,只是将值赋给了b
system("pause");
return 0;
}
总结:函数返回时都会创建一个临时变量,引用返回也会创建一个临时变量,但是这个临时变量并不开辟空间,而是返回值的一个引用。可以用引用接收(不是static修饰的值得不到保证),适用于静态和全局变量。也可以不使用引用接收,只是将值赋给了接收变量,值得到了保障。
返回值不是应用,会创建一个临时变量,会临时开辟空间,并且该临时变量具有常量性质。
5.传值和传引用,返回值和返回引用的效率说明
以值作为参数或者返回值,在传参数和返回期间,函数不会直接传递给实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,由上可知要开辟临时空间。因此效率时很地下的,而使用引用作为参数和返回值时,并不需要开辟空间。
因此传值,返回值比传引用和返回引用的效率低。
6.引用和指针的区别
在语法概念上,引用没有独立的空间,而是和实体公用一块空间。指针在32位机器下占4字节空间,在64位机器下占8字节空间。
在底层实现上,引用实际时有空间的,因为引用时按照指针来实现的。
可以发现,在汇编下,引用和指针实现时一样的。
指针与引用的不同点:
- 引用在概念上是定义一个变量的别名,指针存储一个变量的地址。
- 引用在定义时必须初始化,指针没有要求。
- 引用在引用一个实体后,不能再引用其它实体,指针在任何时候都可以指向一个同类型的实体。
- 没有NULL引用,指针可以指向NULL。
- 在sizeof中含义不同,引用的结果是引用类型的大小(int&类型是int)。但是指针始终是地址空间所占字节大小(在32位机器下占4字节空间,在64位机器下占8字节空间)
- 有多级指针,没有多级引用。
- 访问实体不同,指针需要显式解引用,引用编译器自己处理。
- 引用加1,为实体数值加1。指针加1,为加上指向类型的大小。
- 引用比指针使用起来相对安全。
以上是关于C++之引用怎么用的主要内容,如果未能解决你的问题,请参考以下文章