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

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,所以返回的引用就不能被修改了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏醒者呆

正则表达式——Java程序员懂你

正则表达式 关键字:正则表达式,Pattern,Matcher,字符串方法,split,replace 前文书立下了一个flag,这里要把它完成,就是正则...

3435
来自专栏WindCoder

Java中的域与变量

Java中的Field译为“字段”,也译为“域”,Field和成员变量(Member Variable)是相同的。所以域是变量中的一种。

401
来自专栏IT杂记

String类replaceAll方法正则替换深入分析

背景:     前几天有人发了一个关于下面问题的贴,对这个有点好奇,故花时间做了点研究。     对单个反斜杠字符串替换成双斜杠的Java实现如下: ...

18310
来自专栏Android 研究

Android JNI学习(四)——JNI的常用方法的中文API

本文主要是结合JNI的常用接口文档进行的翻译主要是帮助我们更好的理解JNI中常用的API。具体如下:

561
来自专栏Nian糕的私人厨房

JavaScript 常见面试题分析(二)

④ call() 方法 apply() 方法 bind() 方法 (this 指向第一个参数)

783
来自专栏大前端_Web

jsvascript—谜之this?

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

984
来自专栏静晴轩

Javascript数组操作

使用JS也算有段时日,然对于数组的使用,总局限于很初级水平,且每每使用总要查下API,或者写个小Demo测试下才算放心,一来二去,浪费不少时间;思虑下,堪能如此...

3848
来自专栏Golang语言社区

[Go语言]从Docker源码学习Go——指针和Structs - lemon_bar

http://www.cnblogs.com/lemonbar/p/3932981.html 主题 Go语言 Docker function和method关...

3494
来自专栏前端架构

谈谈javascript语法里一些难点问题-js变量, 栈区,作用域

这是一个令人诧异的结果,为什么第一个弹出框显示的是undefined,而不是1呢?这种疑惑的原理我描述如下:

581
来自专栏小古哥的博客园

JavaScript闭包的深入理解

闭包算是javascript中一个比较难理解的概念,想要深入理解闭包的原理,首先需要搞清楚其他几个概念: 一、栈内存和堆内存 学过C/C++的同学可能知道,计算...

3497

扫码关注云+社区