C++中的新特性:引用
发布日期:2022-02-07 06:39:44 浏览次数:6 分类:技术文章

本文共 3202 字,大约阅读时间需要 10 分钟。

先放一个例子


swap函数对比(作用,交换两个数的数值)

void swap(int *a, int *b)//使用指针{    int temp = *a;    *a = *b;    *b = temp;    return ;}void swap(int &a, int &b)//使用引用{    int temp = a;    a = b;    b = temp;    return ;}

什么是引用


引用,就是一个变量的别名

再来一个例子

int a = 2;int & ra = a;

这里,我们定义ra,它是变量a的引用

下面会用上面定义的变量
放几个引用的用法

引用玩法1

int a = 2;int & ra = a;ra = 3  //!!

如果使用了上面那一条语句会怎样呢?

实际上
此时ra == 3 并且 a == 3
没有动a啊,a为什么会变啊

复习引用的定义

引用就是某一变量的别名

也就是说,变量ra 就是 变量a

我对ra变量执行的任何操作
等同于对a变量执行的任何操作
反之亦然

其实很好理解原理

变量a的地址和变量ra的地址是相同的
(可以自己在编译器上试一试)

引用玩法2

还是一个例子

void function(int & r){
r = 6;}int main(){ int a = 2; function (a); cout << a;}

将a作为形参传入函数

最后会输出多少呢?
????
实际上,会输出6
也就是说,a的值被修改为6

不是只有传入指针才会修改它的值的吗?

再来复习一下

引用也就是说是变量的别名
还有原理
引用变量和原变量地址是相同的


在函数声明中

void function(int & r)

定义了一个引用r

也就是说,r变量将会是传入实参的引用
因此
我们对r怎样
也就是对实际传入变量怎样

再来看回开头的例子

相信大家应该都懂了

关于概念


按值传递

(就是直接传数)
按址传递
(就是传入地址指针)
按引用传递
(就和前面讲到的一样)

为什么用引用


1. 好打,好看

自行对比

什么时候不小心打少了个*号的时候
什么时候*号和++优先级搞错的时候
(*a++ 的理解!!)
……
就会知道引用的方便了。

void swap(int *a, int *b)//使用指针{    int temp = *a;    *a = *b;    *b = temp;    return ;}void swap(int &a, int &b)//使用引用{    int temp = a;    a = b;    b = temp;    return ;}

2. 效率高

这里会扯到一个是否生成临时变量的问题

  1. 按值传递

按值传递的最大优点就是在函数中无论怎么修改变量

都不会改变传入变量的值

原因便在于按值传递中函数内的是临时生成的变量

和传入的变量完全没有关系

  1. 生成临时变量如何影响效率

也许生成一个int变量效率差别不大

但是如果是传入一个有着好几个数组的结构体
或者是一个庞大的类对象
计算机声明这些的临时变量的时候
将会耗费不少计算资源与存储空间
这个时候,把形参定义为引用便显得尤为重要

引用可以同时具有引用优点和按值传递的优点

按值传递的最大优点就是不怕传入的变量被修改

引用可以吗??

我们可以这样子定义来避免变量被改动

void function(const int & a);

通过把a定义为常值引用(加一个const)

我们可以在兼顾引用效率高优点的同时
避免不小心被修改
若是a的值被修改编译器会马上报错方便修改

关于引用的几点注意事项


1. 函数形参有引用

void function ( int & r)为例

我们可以这样子调用吗?

int a = 2;function(a+2);function(4);

前面提到

引用的原理便是内存地址相同
可是,这里的(a+2)有地址吗?
可是,这里的4有地址吗?

我们可以这样用吗?

事实上,这里讲的引用的全名是左值引用

左值:能够放在赋值语句左边的东东
(也就是可被赋值,有自己的内存地址)
能够进行左值引用的一定前提是左值!!

a+2 ,4 明显不能够放在赋值语句左边

(a+2 = 5? 4 = 2?)
因此此时编译器会报错


这里有例外:const引用

如果是void function (const int & r)
那么这个时候我
function(a+2)不会出错
并且,会像按值传递那样生成临时变量
下面有一个总结

int x;int f ( int & n);f(x);f(x+2);// errorf(10);//error , too.int f2 (const int & n);f2(x);f2(x+2);// temporary variablef2(10);// temporary variable

关于返回引用

// 读取一个引用,返回一个引用int & function (int & a){    int b = 2;    a = a + b;    return a;    //返回一个引用}

这里有几个比较容易出错的地方

1. 我可以返回b吗?

再复习一遍原理

引用变量和原变量内存地址一样!
如果这个程序改成

int & function (int & a){    int b = 2;    b = a + b;    return b;    //返回一个引用}

将会报错!!

b 是一个局部变量

局部变量在代码块内可见
当退出代码块时自动销毁!
原内存地址的内容将会消失

假设我int一个变量c

int a = 2;
c = function(a)
变量c的地址将会与函数中临时创建的局部变量b相同
但是函数一旦结束
该地址所对应的内存块将会自动释放!!
此时变量c内的内容将不可访问(或者是垃圾数据)

返回引用(是个左值)

// 读取一个引用,返回一个引用int & function (int & a){    int b = 2;    a = a + b;    return a;    //返回一个引用}

对这个函数,我们有一个比较奇葩的用法

function (a) = 3;

原理其实很简单

因为函数返回值是个左值
所以可以放在赋值语句的左边

那这条语句到底做了什么呢?

1. 函数function接受变量a,
2. 函数体内,返回变量a的引用
3. 对变量a的引用,赋值给3;

所以最终,就是a = 3;


如果怕自己搞错

写出这样的代码
if ( (function(a) = 4 );
(是不会报错的!)
可以把函数声明改成这样
const int & function(int & a);

还有一种奇葩用法

int a = 2;const int & r = a;

这里,a和r实际上是同一个变量

(引用的定义?变量别名)

可是,同一个变量,

我用a就可以赋值,就可以修改
我用r就不能够赋值和修改
(因为用了const)


关于指针,引用,传值的选择

  1. 如果向函数中传递数组,只能用指针
  2. 如果需要修改传入的变量,用引用和指针(引用更好)
  3. 如果传递比较大块的东东,推荐引用或指针(当然引用更好)
  4. 如果怕传入的变量被修改,请用const限制
  5. 没有如果了

总结

  1. 引用必须是左值
  2. 引用可以提高效率
  3. 不能反悔局部变量的引用
  4. 避免引用被修改可以用const来限制
  5. 数组不能引用!对于数组只能使用指针
  6. debug的时候你会有更多的总结

一些比较高级的东西

  1. 对于类的引用,既可以引用该类
    也可以引用该基类的派生类
    (这是实现多态的基础)
  2. c++11中还有右值引用

转载地址:https://blog.csdn.net/wyfwyf12321/article/details/54634054 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C++中的内存分配
下一篇:C++中的函数新特性

发表评论

最新留言

不错!
[***.144.177.141]2024年03月21日 14时16分46秒