初识C++ (三)
创始人
2024-04-01 11:28:11

初识C++ 三

  • 引用
    • 一. 引用的概念
      • 代码演示
    • 二. 引用特性
      • 1. 引用在定义时必须要初始化
      • 2. 一个引用可以有多个实体
      • 3. 引用一旦引用一个实体,再不能引用其他实体
    • 三. 使用场景
      • 1. 做参数
      • 2. 做返回值
        • 内存销毁后空间还在吗?
        • 内存销毁后我们还能访问嘛?
      • 结论
      • 优点
    • 四. 传值传引用的效率比较
    • 五. 引用与重载函数
    • 六. 常引用
      • 右值为常数问题
  • 总结

在这里插入图片描述
如果有什么想要去做的事情就立马去做
全部做完了收收心 继续投入学习!

引用

一. 引用的概念

“引用(Reference)是 C++ 相对于C语言的又一个扩充。引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据。

具体是什么意思呢?

我们这里来举个例子

比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

那你叫铁牛 他会答应你

你叫黑旋风 他也会答应你

在这里插入图片描述

代码演示

我们下面来写一段代码试试

int main()
{int a = 10;int& b = a;return 0;
}

这段代码是什么意思呢?

我们假设这个a是李逵

那么这个b就是黑旋风的意思了!

我们打印这两个变量的地址来看看

在这里插入图片描述
它们的地址一样的 都是李逵!

在这里插入图片描述

注意:引用类型必须和引用实体是同种类型的

比如说像我们这样子

在这里插入图片描述
这里就是一个错误代码

二. 引用特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体

1. 引用在定义时必须要初始化

在这里插入图片描述
这里如果不初始化就会报错 不用多讲了

2. 一个引用可以有多个实体

我们有代码如下

int main()
{int a = 10;int& b = a;int& c = a;//char& c = a; 不能改变类型printf("%p\n", &a);printf("%p\n", &b);printf("%p\n", &c);return 0;
}

在这里插入图片描述

这里它们的地址全部都一模一样 就可以说明它们都是一个地址的别名了

3. 引用一旦引用一个实体,再不能引用其他实体

这句话是什么意思呢?

就拿我们的c来说

他已经引用了a了 还能不能引用其他变量呢

在这里插入图片描述

我们可以发现 它们的地址是没有变化的 那么

    c=d;

这一步代码 到底改变了什么呢?

我们画图来看看

在这里插入图片描述

我们来验证下我们的理论正确不正确

在这里插入图片描述
这里就可以发现 a b c的值全部都变成20了

三. 使用场景

1 . 做参数
2 . 做返回值

1. 做参数

我们来看下面的代码

要求: 交换两个变量的值

void swap(int x, int y)
{int tmp = 0;tmp = x;x = y;y = tmp;
}

可是上面这段代码真的能够交换两个变量的值嘛?

看过我的这两篇博客的同学应该知道 答案是 不能

函数栈帧(上)

函数栈帧(下)

为什么呢?

因为x y只是我们要交换的函数的临时拷贝

交换它们的值并不会对要交换的值有什么影响

那么结合我们今天学到的知识

同学们有没有想到一种巧妙的解法呢?

没错! 就是引用传参

我们写出下面这样子的代码

void swap(int& x, int& y)
{int tmp = 0;tmp = x;x = y;y = tmp;
}

将它们的别名传进去 就可以啦

思考题:
我们都知道 在单链表头插尾插的时候 为了防止头指针为空的情况 我们就需要传递一个二级指针进去
这样子很麻烦
那么使用我们的引用机制如何修改它呢?

答案就是! 将指针的别名(引用)作为参数传递进去 那么修改引用参数是不是就可以了?

如果不能理解的话这样子

李逵吃饱了是不是就等于黑旋风吃饱了?

我们之后再来看以下代码

#include 
struct A { int a[10000]; };void TestFunc1(A a) {}
void TestFunc2(A& a) {}void TestRefAndValue()
{A a;int begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1(a);int end1 = clock();int begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2(a);int end2 = clock();cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}int main()
{TestRefAndValue();return 0;
}

在这里插入图片描述
我们可以发现使用两个函数运行的时间竟然相差很多!

这是为什么呢?

这里就设计到一个传值和传引用的区别(大家类比下传值和传址)
传值需要将整个a拷贝一份
而我们使用引用的话不会拷贝 时间就差在这里

2. 做返回值

还是一样 我们先来看这么两段代码

int& Count()
{static int n = 0;n++;// ...return n; }
int Count()
{int n = 0;n++;// ...return n;
}

在这里插入图片描述
这两段代码的返回值都是1

但是它们返回的方式可不同

我们先来看第二个代码

int Count()
{int n = 0;n++;// ...return n;
}

当我们调用count()这个函数的时候 它会开辟一个新的内存空间在这里临时空间里面设置一个n变量

将n的值加加

到了这一步的时候

return n;

将n的值放到寄存器里面返回

再来看看你第一个代码

int& Count()
{static int n = 0;n++;// ...return n; }

前面的过程几乎一样

注意! 这时候它的返回参数是 int&

也就是说 它直接是把n返回过来了!

不知道大家能不能看出来区别

一个是返回到寄存器中 一个值直接返回n的值

那么这里就引出一个很危险的操作!

int& Count()
{int n = 0;n++;// ...return n; }

我们将static去掉 这个时候n彻底变成局部变量了!

这个时候我们打印一下试试看
在这里插入图片描述

咦?

竟然还是1 难道说局部全局变量没有影响嘛?

当然不是!!!

我们再来写出以下代码

void test()
{cout << "hello world" << endl;
}int main()
{int& ret = Count();cout << ret << endl;test();cout << ret << endl;return 0;
}

在这里插入图片描述
我们发现! 竟然ret变成随机值了!

这是为什么呢?

因为我们实际上得到的ret是n的别名 但是呢在函数结束调用之后所有的参数就被销毁了(这其中也包括n) 当我们运行另外的一个函数来调用栈空间的时候 有可能就将n地址的内容改变了 所以说造成了这个现象

那么这里就引用出两个问题

内存销毁后空间还在吗?

空间还在 但是已经不属于我们了

内存销毁后我们还能访问嘛?

可以访问 但是里面的数据的读写我们都不能确定

结论

1 出了函数作用域,返回变量不存在了,不能用引用返回,因为引用返回的结果是未定义的。
2 出了函数作用域,返回变量存在,才能使用引用返回。

优点

可以修改返回值

比如说

在这里插入图片描述
如果说我们使用 int 来接受ret的话那么只能够每次都给ret赋值了

四. 传值传引用的效率比较

参考做参数 使用场景1中的举例

五. 引用与重载函数

我们来看以下代码
在这里插入图片描述

这两个函数显然是构成重载函数的

但是我们却不建议这么写

因为很有可能造成歧义

比如说你打出下面的代码

test(10);

那么你究竟是想调用谁呢?

六. 常引用

这里牢记一个概念就好
我们引用一个变量的时候所具有的权限只能小于等于该变量

例如

int main()
{// a具有读写能力int a = 10;int& b = a;// 可以const int& b = a;// 权限缩小 可以const int c = 20;int& d = 20;// 权限放大 不可以const int& d = 20;// 权限相同 可以return 0;
}

在这里插入图片描述

右值为常数问题

常数是不可以被改变的 所以说没有写权限

其实不是不能引用而是权限不匹配

如果一定要可以用以下方式写代码

    const int& a = 10;// 读写权限匹配cout << a << endl;

在这里插入图片描述

总结

在这里插入图片描述

以上就是关于c++引用博主一些浅薄的理解啦
如果出现错误希望大佬们指正!
阿尼亚 哇酷哇酷!

相关内容

热门资讯

长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...