C++学习 九、引用

C++学习 九、引用

  • 前言
  • 引用变量
    • 创建引用变量
    • 引用的本质
  • 函数与引用
    • 引用参数
    • 返回引用
  • 左值,右值,左值引用,右值引用
    • 左值lvalue与右值rvalue
    • 左值引用
    • 右值引用
  • 后记

前言

本篇继续C++学习记录,引用。

引用变量

引用是C++与C的一大扩展。引用变量是已定义变量的别名。

创建引用变量

与其它变量不同,引用变量必须在声明的同时初始化,通过&标识,如下所示:

int a;
int& aa = a;

此时,&不再表示取地址,int&表示整型引用。

变量a与引用变量aa的值和地址是相同的。因此,修改a或者aa都会使对方出现相同的改变。

此外,引用变量初始化之后,就不能修改引用的“指向”了,这点和指针不同。

引用的本质

引用的本质,实际上是一个指针常量:

// 引用
int i;
int& ii = i;
// 实质
int* const pi = &i;

引用变量ii*pi完全一致。

指针常量保存的地址不能被改变,这也就是创建引用变量后不能再修改“指向”的原因。

函数与引用

上篇函数内容中提到两种传参方法,也就是传值和传址。C++提供的第三种传参方法,就是传引用。

通过传引用,函数也可以像传址一样修改函数外部的变量。

引用参数

还是以经典的二值交换函数为例,通过引用参数:

void swap(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}
void main(){
	int x = 1;
	int y = 2;
	swap(x, y);
}

调用函数时,swap函数内的引用a, b作为外部变量x, y的别名,函数内部a, b值交换,外部变量也将跟着交换。这一点从地址的角度来看更容易理解,因为a, b的地址与x, y相同。

引用的本质是指针常量,因此传参时也不会拷贝被引用者的完整数据。

注意:无论是引用变量,还是引用参数,非const引用类型必须一致。下面的程序将报错:

#include 
#include 

void swapr(double& a, double& b){
	double temp = a;
  	a = b;
  	b = temp;
}

int main()
{
  	using namespace std;
  	float x=1., y=2.;
  	swapr(x, y);
  	cout << x << ", ,"<< y <<endl;	
  
  	return 1;
}
error: cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double'
    swapr(x, y);

如果引用变量类型与被引用的变量类型不同,C++会生成临时变量。

由于函数内部创建的变量在函数结束时销毁,修改临时变量是没有意义的,因此编译器认为非const引用参数生成的临时变量是没有意义的。这就是上面报错的原因。

有关const关键字的使用将在下篇C++学习中详细记录。

返回引用

函数常规返回的方式是按值返回,也就是函数把返回值复制到某个内存的某个临时位置,然后被程序访问,示例如下:

int func(int a){
	return a;
}
void main(){
	int x;
	int y = func(x);
}

上面的程序中,func1返回a时,在内存中临时创建了一个保存a值的空间,然后主程序从该临时空间里的值拷贝到变量y。

如果返回的是结构或者对象,那么函数把返回的结构或对象复制到内存中,然后再让程序来访问。这样就非常消耗时间和内存了。

返回引用则不会在内存中创建临时空间,而是直接将引用变量返回。返回引用的函数声明为TypeName& FuncName(ParamList)。示例如下:

int& func(int &a){
	return a;
}
void main(){
	int x;
	int y = func(x);
}

上面的程序中,func1直接返回引用变量a,主程序拷贝a的值。

注意:返回引用时,禁止返回局部变量,也就是说不能返回函数结束后被销毁的变量。指针同理。上面返回引用的函数中,参数列表也使用了引用参数,就是为了延长a的生命周期。

左值,右值,左值引用,右值引用

左值lvalue与右值rvalue

最简单的判断方法:能取址的是左值,不能取址的是右值。

也就是说,左值在内存空间中占据确定的位置,而右值则只是在计算过程中被临时创造,没有确定的内存空间,计算结束即销毁。

左值引用

一般而言,左值才能被引用。上面提到的引用都是左值引用。因此,不特殊声明时认为,引用就是左值引用。

左值引用:

float v;
float& lv = v;

右值引用

C++11中添加了右值引用,也就是可以引用右值,通过&&创建:

double&& j = 15. + .5;

右值引用被用于std::move()的实现,以后会学习到。

后记

引用的本质:指针常量。

使用引用参数的好处:

  • 可以修改实参
  • 省去拷贝数据的内存和时间,提升效率

因此,引用与指针一样,适合用作访问和修改大型数据。典型的例子是通过传指针在函数内修改数组,通过传引用在函数内修改结构和对象。

你可能感兴趣的:(C++与数据结构,c++,c语言,开发语言)