1.引用的概念及用法
在C++中,有一种特殊的语法结构叫做引用,那什么叫做引用呢?引用是c++对c语言的一个重要扩充,换句话说,引用就是给某个变量取一个新的别名。引用的语法结构为:类型& 引用名(别名)=目标变量名。
例如:int a=0;int& b=a;这条语句的意思为:定义变量a=0,b是变量的别名。
在
内存中的存储我们可以这样理解:有一块空间,空间里面的内容为0,这个空间的名字为a,还有另一个别名叫做b。在定义引用的时候在语法层面上来说并没有给b开辟额外的空间。在定义了b是a的别名后,可以通过变量b来修改a的值。但是我们需要注意的一点是如果定义a时加上了const限定符,即:const int a=0;那么如果我们在定义引用还是如int& b=a;这样定义的话,编译便会报错。因为a在加上const限定符后,从编译器的角度来讲,a的值是不希望被后续修改的,这里我们还想企图定义b来通过别名去修改它,这显然是不符合逻辑的。要想编译通过,我们必须在定义引用时也加上const修饰。即:const int& b=a;
2.引用的特性
特性一:一个变量可以定义多个别名,例如:定义int a=10;还可以定义int& b=a;int& c=a;即b和c都是a的别名,但是b和c在定义为a的别名之后就不可以再定义为其他变量的别名。
特性二:引用在定义的时候必须对它进行初始化。很好理解,既然引用是别名,那么你要给谁取别名必须要清楚吧!
特性三:引用在初始化时引用一次,不能改变再成为其他变量的别名。例如:int a=0;int& b=a;b初始化为a的别名之后,就不能再成为其他变量的别名了。
3.引用做参数
函数在进行传参的时候有三种方式,分别为:值传递,引用传递和指针传递。
第一种:值传递
例如:
int add(int a,int b)
{
return a+b;
}
int main()
{
int ret=add(1,4);
return 0;
}
形参为传值方式,在形参实例化的过程中会生成临时变量a和b来接收实参传过来的值,这里比较简单,我们不必多说。
第二种:传引用
如果函数的形参为引用类型,则形参相当于实参的别名,我们如果想对实参进行修改就可以直接使用形参来进行修改。传引用的好处在于不用开辟临时空间来保存函数参数,即节省空间开销。但是如果我们不希望函数在进行传参事它的值被修改,那么我们便可以使用常引用传参。例如:
void Func(const int&a)
{
//如果这里对a进行了改变,那么编译器肯定是会有警告的
}
第三种:传指针(地址)
显然,传地址就是把变量的地址作为函数参数。
例如我们常见的Swap函数,此处我们便可以通过Swap函数来比较一下三种传参方式。
void Swap(int a,int b)
{
int tmp=a;
a=b;
b=tmp;
}
我们都知道用这种传值的方式是无法交换两个变量的值的,为什么?因为函数在调用时形参会进行实例化,形参在实例化时会生成临时空间,形参a和形参b都在这个临时空间里存放,当我们在进行交换时仅仅只是交换了临时空间里的a和b的值,而调用Swap函数的调用方里的实参并未发生交换。
所以这个时候我们就必须进行传地址或者传引用。
//传引用
void Swap(int& a,int& b)
{
int tmp=a;
a=b;
b=tmp;
}
//传指针
void Swap(int *a,int *b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
显而易见这两种做法都是可以的,拿那种做法更好呢,当然是传引用,节省空间,效率高!
总结,其实引用传参是 很好的选择,这个例子看起来还不够明显,如果我们传参的时候需要传一个很大很大的结构体呢,设想一下,是不是引用传参的优势就突出了呢。
4.引用做返回值
int& ADD(int a,int b)
{
int ret=a+b;
return ret;
}
int ADD(int a,int b)
{
int ret=a+b;
return ret;
}
我们来通过汇编了解一下传值和传引用的区别:
值返回:传值返回时,是将ret的值放在eax里。
引用返回:将ret的地址放在eax里。
lea指令:lea指令的源操作数是一个变量符号,将变量的地址取出来放到目标操作数中。
总结一下:第一,不要返回一个临时变量的引用,第二,如果返回对象出了函数作用域依然在,使用引用返回更高效。
5.汇编层看引用
int main()
{
int a=10;
int& b=a;
return 0;
}
我们来通过汇编代码看一下引用在底层到底是如何实现的。
此时我们可以看到在创建a的别名b的时候,是把a的地址保存到了b里,实际上b也是开辟了空间的。
6.引用和指针的区别
第一:引用只能在初始化时被初始化一次,之后不能改变它指向其他变量;但指针变量的值可以被改变。
第二:引用必须指向一个有效的值;但是指针可以指向空;
第三:指针和引用的自增和自减意义不一样,指针的++或者--是加上或者减去它所指向类型的大小。但引用的++和--为+1或者-1。
第四:sizeof对指针和引用求值不一样,sizeof(引用)是指所指向变量的大小;sizeof(指针)结果为对象地址的大小。
第五:从一定程度上来说,指针比引用更安全。因为指针存在野指针及对空指针进行解引用等一系列问题。’