引用变量!

引用变量

引用是已定义的变量的别名(另一个名称)。但引用变量的主要用途是用作函数的形参。通过将引用变量用作参数,函数将使用原始数据,而不是其副本。

创建引用变量

C和C++使用&符号来指示变量的地址。C++给&符号赋予了另一个含义,将其用来声明引用。例如,要将rodents作为rats变量的别名,可以这样做:
int rats;
int & rodents = rats; //makes rodents an alias for rats
其中,&不是地址运算符,而是类型标识符的一部分。就像声明中的char指的是指向char的指针一样,int&指的是指向int的引用。它们指向相同的值和内存单元。
必须在声明引用时将其初始化。
引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它。也就是说,
int & rodents =rats;
实际上是下述代码的伪装表示:
int * const pr = &rats;
其中,引用rodents扮演的角色与表达式
pr相同。

将引用用作函数参数

引用经常被用作函数参数,使得函数中的变量名称为调用程序中的变量的别名。这种传递参数的方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量

引用的属性和特别之处

如果程序员的意图是让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用。例如: double refcube (const double &ra);
顺便说一句,如果要编写类似上面的代码的函数,应采用按值传递的方式。而不要采用按引用传递的方式。
如果函数形参是引用,实参应是变量,而不能是表达式。

临时变量、引用参数和const

如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用时,C++才允许这样做,但以前不是这样的,下面来看看何种情况下,C++将生成临时变量,以及为何对const引用的限制是合理的。
首先,什么时候将创建临时变量呢?如果引用参数是const,则编译器将在下面两种情况下生成临时变量:
 实参的类型正确但不是左值;
 实参的类型不正确,但可以转化为正确的类型。
左值是什么?左值参数是可被引用的数据对象,例如,变量,数组元素,结构成员,引用和解除引用的指针都是左值。非左值包括字面常量(用引号括起的字符串除外,它们又其地址表示)和包含多项的表达式。在C语言中,左值最初指的是可出现在赋值语句左边的实体,但这是引入关键字const之前的情况。现在,常规变量和const变量都可视为左值,因为可通过地址访问他们。但常规变量属于可修改的左值,而const变量属于不可修改的左值。
回到前面的示例。假设重新定义了refcube(),使其接受一个常量引用参数。
double refcube(const double &ra)
{
return rarara;
}
现在考虑下面的代码:
double side = 3.0;
double * pd = &side;
double & rd = side;
long edge = 5L;
double lens[4] = { 2.0, 5.0, 10.0, 12.0};
double c1 = refcube(side); //ra is side
double c2 = refcube(lens[2]); //ra is lens[2]
double c3 = refcube(rd); //ra is rd is side
double c4 = refcube(*pd); //ra is pd is side
double c5 = refcube(edge); //ra is temporary variable
double c6 = refcube(7.0); //ra is temporary variable
double c7 = refcube(side + 10.0);//ra is temporary variable
参数side、lens[2]、rd和
pd都是有名称的,double类型的数据对象,因此可以为其创建引用,而不需要临时变量。然而,edge虽然是变量,类型却不正确,double引用不能指向long,另一方面,参数7.0和side+10.0的类型都正确但没有名称,在这些情况下,编译器都将生成一个临时匿名变量,并将ra指向它。这些临时变量只在函数调用期间存在,此后编译器便可以随意将其删除。
那么为什么对于常量引用,这种行为是可行的,其他情况下却不行的呢?对于下面函数swapr()
void swapr(int &a, int &b) //use references
{
int temp;
temp = a; //use a, b for values of variables
a=b;
b=temp;
}
如果在早期C++较宽松的规则下,执行下面的操作将发生什么情况呢?
long a = 3, b = 5;
swapr(a, b);
这里类型不匹配,因此编译器将创建两个临时int变量,将它们初始化为3和5,然后交换临时变量的内容,而a和b保持不变。
简而言之,如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。解决方法是 禁止创建临时变量,现在的C++标准正式这样做的(然而,在默认情况下,有些编译器仍将发出警告,而不是错误消息,因此如果看到了有关临时变量的警告,请不要忽略)
现在来看refcube()函数,该函数的目的只是使用传递的值而不是修改它们,因此临时变量不会造成任何不利的影响,反而会使函数在可处理的参数种类方面更通用。因此,如果声明将引用指定为const,C++将在必要时生成临时变量。实际上,对于形参为const引用的C++函数,如果实参不匹配,则其行为类似于按值传递。为确保原始数据不被修改,将使用临时变量来存储值。

应尽可能使用const

将引用参数声明为常量数据的引用理由有三个:
 使用const可以避免无意中修改数据的编程错误;
 使用const是函数能够处理const和非const实参,否则将只能接受非const数据;
 使用const引用使函数能够正确生成并使用临时变量。
因此,应尽可能将引用形参声明为const。
C++11新增了另一种引用——右值引用(rvalue reference)。这种引用可指向右值,是使用&&声明的:
double && rref = std::sqrt(36.00); //not allowed for double &
double j = 15.0;
double &&jref = 2.0*j+18.5; //not allowe for double &
std::cout<< rref <<’\n’ ; //display 6.0;
std::cout<<jref << ‘\n’; //display 48.5;
新增右值引用的主要目的是,让库设计人员能够提供有些操作的更有效实现。第18章将讨论如何使用右值引用来实现移动语义(move semantics)。以前的引用(使用&声明的引用)现在成为左值引用。

	**摘录整理自《C++ Primer Plus》**
	By_Suki 2020/4/13
发布了29 篇原创文章 · 获赞 27 · 访问量 2952

猜你喜欢

转载自blog.csdn.net/Eumenides_Suki/article/details/105480135
今日推荐