C++引用变量笔记

来源:互联网 发布:cf网截分析数据 编辑:程序博客网 时间:2024/06/16 09:09

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

创建引用变量

c和c++使用&符号来指示变量的地址。c++给&赋予了另一个含义,将其用来声明引用变量。例如,将rodents作为rats变量的别名,可以这样做

int rats;int & rodents = rats;  //makes rodents an alias for rats

&不是地址运算符,而是类型标志符的一部分。int & 是指向int的引用。上述引用声明允许rats与rodents互换—他们指向相同的值与内存单元。

对于C语言用户而言,首次接触到引用时可能会有些困惑,因为这些用户很自然的想到指针,但是他们之间是有区别的。例如,可以创建指向rats的引用和指针:

int rats = 101;int & rodents = rats; //rodents a referenceint * prats = &rats; //prats a pointer

这样,表达式rodents(值)和*prats(值)都可以与rats(值)互换,而表达式&rodents(地址)与prats(地址)都可以通&rats(地址)互换。从这一点上来看,引用很像伪装表示的指针。但是,引用还是不同于指针的。除了表示法不同外,差别之一是,必须在声明引用时将其初始化,而不能像指针那样,先声明,再赋值:

int rat;int & rodent;rodent = rat;  //No, you can't do this

注意:必须在声明引用变量时进行初始化。
引用更接近construction指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于他。也就是说:

int & rodents = rats;

实际上是下述代码的伪装表示:

int * const pr = &rats;

其中,引用rodents扮演的角色与表达式*pr相同。

将引用用作函数参数

引用经常用作函数参数,使得函数中的变量名成为调用程序中的变量别名。这种传递参数的方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。C语言只能按值传递,按值传递导致被调用函数使用调用程序的值的拷贝。C语言避开按值传递的限制使用的是按指针传递方式。

//swap.cpp --- swapping with references and with points#include <iostream>void swapr(int & a, int & b);   //a,b are aliases for intsvoid swapp(int * p, int * q);   //q,q are addresses of intsvoid swapv(int a, int b);       //a,b are new variablesint main(){    using namespace std;    int wallet1 = 300;    int wallet2 = 350;    cout << "wallet1 = $" << wallet1;    cout << " wallet2 = $" << wallet2 << endl;    cout << "Using references to swap contents:\n";    swapr(wallet1, wallet2);  //pass variables    cout << "wallet1 = $" << wallet1;    cout << " wallet2 = $" << wallet2 << endl;    cout << "Using pointers to swap contents again:\n";    swapp(&wallet1, &wallet2);  //pass addresses of variables    cout << "wallet1 = $" << wallet1;    cout << " wallet2 = $" << wallet2 << endl;    cout << "Trying to use passing by value:\n";    swapv(wallet1, wallet2);   //pass values of variables    cout << "wallet1 = $" <<wallet1;     cout << " wallet2 = $" << wallet2 << endl;    return 0;}void swapr(int & a, int & b)  //use references{    int temp;    temp = a;   //use a,b for values of variables    a = b;     b = temp;}void swapp(int * p, int * q)  //use pointers{    int temp;    temp = *p;    //use *p,*q for values of variables    *p = *q;    *q = temp;}void swapv(int a, int b)  //try using values{    int temp;    temp = a;   //use a, b for values of variables    a = b;     b = temp;}

运行结果
比较函数swapr()(按引用传递)与swapv()(按值传递)的代码。唯一的外在区别是声明函数参数的方式不同。

void swapr(int & a, int & b)void swapv(int a, int b)

内在的区别在于,在swapr()中,变量a和b是wallet1和wallet2的别名,所以变换a和b的值相当于交换wallet1与wallet2的值,但在swapv()中,变量a和b是复制了wallet1与wallet2的值的新变量,因此交换a与b的值不会影响wallet1与wallet2的值。

比较函数swapr()(传递引用)和swapp()(传递指针)。第一个区别是声明函数参数的方式不同:

void swapr(int & a, int & b)void swapp(int * p, int * q)

另一个区别是指针版本需要在函数使用p和q的整个过程中使用解除引用运算符*。

引用的属性与特别之处

下面看一个例子:

#include <iostream>double cube(double a);double refcube(double &ra);int main(){    using namespace std;    double x = 3.0;    cout << cube(x);    cout << " = cube of " << x << endl;    cout << refcube(x);    cout << " = cube of " << x << endl;    return 0;}double cube(double a){    a *= a * a;    return a;}double refcube(double &ra){    ra *= ra * ra;    return ra;}

运行结果:
这里写图片描述
refcube()函数修改了main()中的x值,而cube()没有,这提醒我们为何通常按值传递。变量a位于cube()中,他被初始化为x的值,但是修改a并不会影响x。但是由于refcube()使用了引用参数,因此修改ra实际上就是修改x。如果想要让函数传递给他信息时不对这些信息进行修改,同时又想使用引用,则应该使用常量引用。例如,在这个例子中,应在函数原型和函数头中使用const:

double refcube(const double & ra);

但是,这样做在进行编译时会生成错误信息,具体报错信息如下:
这里写图片描述

应尽可能使用const
将引用参数声明为敞亮数据的引用的理由有三个:
1. 使用const可以避免无意中修改数据的编程错误;
2. 使用const使函数能够处理const和非const实参,否则只能接受非const数据。
3. 使用const引用使函数能够正确生成并使用临时变量。
因此,应尽可能将引用形参声明为const。

原创粉丝点击