首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++随记(七)--引用变量

C++随记(七)--引用变量

作者头像
TeeyoHuang
发布2017-12-28 14:44:36
9950
发布2017-12-28 14:44:36
举报

C++随记(七)--引用变量

引用变量是C++新增的一种复合类型。引用是 已定义的变量的一个别名(另一个名称)。引用变量的主要用途是用作函数的形参,如果将引用变量作参数,那么就相当于是在对原始变量进行直接操作。

1、引用变量的创建

int Bruce_Wayne;
int & Batman = Bruce_Wayne;

首先我们有一个int 类型的变量:Bruce_Wayne,然后我们定义了一个引用变量:Batman,上述声明允许将Bruce_Wayne和Batman互换,因为它们指向相同的值和内存单元!所以Batman就是Bruce_Wayne,Bruce_Wayne就是Batman。 符号 int &表示符合类型—引用,而且是一个指向int变量的引用。

注意:引用必须在声明的同时进行初始化!

int Bruce_Wayne;
int & Batman;
Batman = Bruce_Wayne;//非法,引用必须要在声明的同时进行初始化,一旦与某个变量关联起来,就必须一直效忠于它。

2、引用作为函数参数

引用经常被作为函数参数,使得函数中的变量名成为调用程序中的变量的别名。这种传递函数的方法叫做----按引用传递。 按引用传递允许被调用的函数能够访问调用函数中的变量。 区别于C语言,C语言提供了按值传递,导致被调用函数使用调用程序的值的拷贝。 当然,C语言也提供了按指针传递来避开按值传递的方式。

简单例子:

void swap1( int & a, int & b)
{
int temp;
temp = a;
a =b;
b =temp;
}

void swap2( int a, int b)
{
 int temp;
 temp = a;
 a = b;
 b = temp;
}

比较这两个函数,唯一不同的地方就是在函数头的位置,前者是引用变量作形参。

假设现在使用这两个函数

swap1( AAA, BBB);//设AAA,BBB是我已经定义好了的int 变量
swap2( AAA, BBB);

能实现二者的值交换的,只有第一个函数,因为第二个函数中的a、b是拷贝了AAA、BBB的值,然后实现大量a、b自己的交换,但是没有对AAA、BBB造成影响,而第一个函数使用引用作为形参,那么第一个函数中的a、b就可以当作是AAA、BBB,所以我实际是在对AAA、BBB进行操作,这就是引用的妙处。 顺便说一句,这里并没有违反引用要在声明的同时初始化的原则,因为函数调用的时候,自动就使用实参来初始化形参。

要注意,一般情况下,将引用变量作形参时,实参应该为变量,例如我这里的AAA、BBB都是int类型的变量,而不能将表达式比如x+3 这种拿来作实参,现在的大多数编译器都会指出这一错误

3、常引用

常引用也是一个非常有用的技巧,我们上面谈到,引用变量和原变量是一回事,也就是说我如果在函数中对引用变量进行操作,就能改变原来的变量,我上面交换数值的函数用的就是这一性质,但是有时候我们会希望避免函数中一些操作对我的原变量产生影响,导致无意中修改了变量数值,那么就可以考虑常引用。 常引用声明方式:const  类型标识符 & 引用名 = 目标变量名; 例如有一函数为:

void exam( const int & a )
{
…
}

那么就表明在此函数中, 引用变量 a 是不能改变值的,这样就能规避a的改变导致我原来作为实参的原变量的改变,整个函数中,可以利用的就只是a的确定的值。

你可能会有疑问,既然只用到了形参的值,那么按值传递不就可以了吗?比如:

void exam(int a )
{
…
}

这样既能够把实参的值传递进来给a,而且也不用担心a的改变会影响原实参的数值。这么考虑确实是对的,但是注意一个问题,我如果使用按值传递的方法,我是创建了新的变量的!即int a 这一步,我会开辟一个新的内存空间来存放值,函数调用完之后又一般会释放这个值。而我的引用呢?const int & a没有创建新的变量!a仍然使用原来实参的储存空间和地址!也就是我没有创建变量这一过程。

在程序运行中,创建新变量消耗的时间是很多的,当然这里的int变量可能感受不到,但是当你的引用类型是结构体、类的时候,你就能明显感觉到了,我曾经把一个程序中的这些按值传递的都改成了常引用,发现最后程序快了几秒!这已经是很可观的了,因为我的程序总共就运行几十秒的时间(当时在千方百计减少程序的运行时间,还是我的老师点拨了我一下)。

所以常引用的优势在于:既保护了原来的实参受到误修改,又充分提升了效率节省了空间!

4、函数返回值为引用

先来看两个函数的对比:

int test1( int a, int b, int sum)
{
  sum = a + b+ sum;
  return sum;
}
//////////////////////////////////////////////////
int & test2( int a, int b, int & sum)
{
  sum = a+b;
  return sum;
}

这两个函数有什么不同呢? 很明显test2 的函数头多了两个 &,这就是函数返回值为引用的意思。首先看到函数被声明为 int & test2, 且参数列表中也至少有一个引用变量作形参, int & sum。

现在来分析这两个函数运行时的区别,

情况①:

int Price = test1( price_1, price_2, result);

首先,price_1, price_2把值传递给a和b,result的值传递给sum,然后经过计算,sum的结果被函数返回,此时将结果复制到一个临时的位置,然后将此值再赋值给 Price。

情况②:

int Price = test2( price_1, price_2, result);

同样price_1, price_2把值传递给a和b,而sum此时是作为result的引用值,所以相当于直接把result拿进去参与计算(当然这不是重点),重点是:result由于和sum是一回事,因此sum被修改后,result也更新了,函数return sum,实际就是return result,所以不需将值复制到一个临时的位置,而是相当于直接把result的值,复制给Price!

同时你会发现当返回值为引用时,以下语句是合法的:

test2( price_1, price_2, result) = 33;

看起来是在对函数赋值,但是这个函数实际上是 result 的别名,所以其实你会发现result的值被修改为33. 当然,如果你不希望返回的引用值出现修改的情况,可以使用const:

const int & test2( int a, int b, int & sum){....}

这样再对其赋值就不合法了,因为定义为了const,所以返回的引用就不能被修改了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-06-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++随记(七)--引用变量
    • 1、引用变量的创建
      • 2、引用作为函数参数
        • 3、常引用
          • 4、函数返回值为引用
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档