0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

c++引用详细解说4

jf_78858299 来源:阿Q正砖 作者:阿Q正砖 2023-02-15 09:43 次阅读

6、效率比较

值和引用的作为返回值类型的性能比较:

#includestruct A { int a[10000]; };A a;// 值返回A TestFunc1() { return a; } // 拷贝// 引用返回A& TestFunc2() { return a; } // 不拷贝void TestReturnByRefOrValue(){    // 以值作为函数的返回值类型            size_t begin1 = clock();    for (size_t i = 0; i < 100000; ++i)            TestFunc1();    size_t end1 = clock();    // 以引用作为函数的返回值类型            size_t begin2 = clock();    for (size_t i = 0; i < 100000; ++i)            TestFunc2();    size_t end2 = clock();    // 计算两个函数运算完成之后的时间            cout << "TestFunc1 time:" << end1 - begin1 << endl;    cout << "TestFunc2 time:" << end2 - begin2 << endl;}int main(){    TestReturnByRefOrValue();    return 0;}

由于传值返回要拷贝,所以当拷贝量大,次数多时,比较耗费时间;而传引用返回就不会,因为返回的就是别名。

图片

对于返回函数作用域还在的情况,引用返回优先。

引用传参和传值传参效率比较 :

#includestruct A { int a[10000]; };void TestFunc1(A a) {}void TestFunc2(A& a) {}void TestRefAndValue(){    A a;    // 以值作为函数参数    size_t begin1 = clock();    for (size_t i = 0; i < 10000; ++i)            TestFunc1(a);    size_t end1 = clock();    // 以引用作为函数参数    size_t begin2 = clock();    for (size_t i = 0; i < 10000; ++i)            TestFunc2(a);    size_t end2 = clock();    // 分别计算两个函数运行结束后的时间    cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;    cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;}
int main(){ TestRefAndValue();}

还是引用快,因为引用减少拷贝次数:

图片

总结:引用的作用主要体现在传参和传返回值

  • 引用传参和传返回值,在有些场景下可以提高性能(大对象 and 深拷贝对象 – 之后会讲)。
  • 引用传参和传返回值,在对于输出型参数和输出型返回值很舒服。说人话就是形参改变,实参也改变 or 返回对象(返回值改变)。

7、常引用

const 修饰的是常变量,不可修改。

图片

a本身都不能修改,b为a的引用,那么b也不可以修改,这样就没意义了。a是只读,但是引用b具有可读可写的权利,该情况为权限放大,所以错误了。

这时,只要加 const 修饰 b ,让 b 的权限也只有只读,使得 权限不变 ,就没问题了:

图片

而如果原先变量可读可写,但是别名用 const 修饰,也是可以的,这种情况为 权限缩小 :

图片

对于函数的返回值来说,也不能权限放大,例如:

int fun(){    static int n = 0;    n++;    return n;}
int main(){ int& ret = fun(); // error
return 0;}

这样也是不行的,因为返回方式为 传值返回 ,返回的是临时变量,具有 常性 ,是不可改的;而引用放大了权限,所以是错误的;这时加 const 修饰就没问题:

const int& ret = c(1, 2)

那么这种情况为什么不可以?

图片

而这样就可以了?

图片

因为类型转换会产生临时变量 :

对于类型转换来说,在转换的过程中会产生一个个临时变量,例如 double d = i,把i转换后的值放到临时变量中,把临时变量给接收的值d

而临时变量具有常性,不可修改,引用就加了写权限,就错了,因为 权限被放大了 。

小结:对于引用,引用后的变量所具权限可以缩小或不变,但是不能放大(指针也适用这个说法)

作用 :在一些场景下,假设 x 是一个大对象,或者是深拷贝对象,那一般都会用引用传参,减少拷贝,如果函数中不改变 x ,尽量用 const 引用传参。

图片

这样可以防止 x 被修改 ,而对于 const int& x 也可以接受权限对等或缩小的对象,甚至为常量:

图片

结论 :const type& 可以接收各种类型的对象(变量、常量、隐式转换)。对于输出型参数用引用,否则用 const type&,更加安全。

8、指针和引用区别

从语法概念上来说,引用是没有开辟空间的,而指针是开辟了空间的,但是从底层实现上来说,则又不一样:

int main(){    int a = 10;
int& ra = a; ra = 20;
int* pa = &a; *pa = 20; return 0;}

汇编

图片

lea 是取地址:我们发现无论引用和指针,都会取地址,且这些过程和指针一样。

其实从汇编上,引用其实是开空间的,并且实现方式和指针一样,引用其实也是用指针实现的。

区别汇总:

  • 引用概念上定义一个变量的 别名 ,指针存储一个变量 地址。
  • 引用 在定义时 必须初始化 ,指针最好初始化 ,但是不初始化也不会报错。
  • 引用在初始化时引用一个实体后 ,就不能再引用其他实体 ,而指针可以在任何时候指向任何一个同类型。
  • 没有NULL引用,但有NULL指针。
  • 在sizeof中含义不同:引用结果为 引用类型的大小,但指针始终是 地址空间所占字节个数 (32位平台下占4个字节)。
  • 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。
  • 有多级指针,但是没有多级引用。
  • 访问实体方式不同,指针需要显式解引用,引用编译器自己处理。
  • 引用比指针使用起来相对更安全。

以上全部是对c++引用的一个详细解读,希望大家受益良多哈。平时在写代码的时候多调试看看里面的原理,看看编译器到底是怎么进行运行的,让自己对编码这块更具有灵性!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7551

    浏览量

    131928
  • C++
    C++
    +关注

    关注

    21

    文章

    2070

    浏览量

    73039
  • 面向对象
    +关注

    关注

    0

    文章

    64

    浏览量

    9936
收藏 人收藏

    评论

    相关推荐

    如何在MDK中使用C++,整理的经验

    一:C++引用C文件注意:C++文件能引用C文件,但是C
    发表于 03-10 15:32

    新手必备嵌入式学习步骤及方法详细解说

      新手必备嵌入式学习步骤及方法详细解说?嵌入式系统的应用非常广泛,因此对于计算机专业、电子信息专业、自动化专业以及机电一体化等专业的学生以及需要掌握嵌人式的人员来说,学习嵌入式系统及其开发应用是
    发表于 06-22 13:35

    详细讲解C++串口的相关知识

    大家可以先参考一下这篇blog,C++串口通信里面详细讲解了C++串口的相关知识,以及一些函数的讲解。下面我也会根据他的blog再讲解。二、实现过程1、打开串口:使用函数:HANDLE CreateFile();HANDLE C
    发表于 08-24 06:56

    IDF.PY编译时提示找不到iostream的原因?怎么才能正常引用iostream这些c++的标准库啊?

    failed with exit code 1我在工程里引用了一个C++的库,里面用了iostream, 在一个C++的.h头文件开头。c++类库我确认都在idf的对应目录下,包括i
    发表于 02-16 06:58

    请问ESP32+Eclipse如何添加C++生成得静态库(.a)如何引用

    ESP32在Eclipse下如何添加C++生成得静态库(.a)如何引用
    发表于 02-20 08:33

    开关电源原理及各功能电路详细解说

    开关电源原理及各功能电路详细解说
    发表于 09-15 17:19 42次下载
    开关电源原理及各功能电路<b class='flag-5'>详细</b><b class='flag-5'>解说</b>

    C++程序设计教程之数组的详细资料说明

    本文档详细介绍的是C++程序设计教程之数组的详细资料说明主要内容包括了:1. 数组的概念,2. 一维数组的定义和引用,3. 二维数组的定义和引用
    发表于 03-14 14:48 10次下载
    <b class='flag-5'>C++</b>程序设计教程之数组的<b class='flag-5'>详细</b>资料说明

    C++引用的使用场景

    C++引用的使用场景
    的头像 发表于 06-29 15:18 3873次阅读
    <b class='flag-5'>C++</b>:<b class='flag-5'>引用</b>的使用场景

    C++中的const和引用的讨论

    今天给大家分享一下这段时间学习c++的总结学习:c++里面的const关键字和引用
    的头像 发表于 12-24 15:35 692次阅读

    C++基础语法中的引用、封装和多态

    本期是C++基础语法分享的第六节,今天给大家来分享一下: (1)引用; (2)宏; (3)成员初始化列表; (4)封装; (5)继承; (6)多态; 引用 左值引用 常规
    的头像 发表于 09-12 09:58 1188次阅读

    c++引用详细解说1

    C++是C语言的继承,它可进行过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
    的头像 发表于 02-15 09:40 427次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>引用</b><b class='flag-5'>详细</b><b class='flag-5'>解说</b>1

    c++引用详细解说2

    C++是C语言的继承,它可进行过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
    的头像 发表于 02-15 09:43 372次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>引用</b><b class='flag-5'>详细</b><b class='flag-5'>解说</b>2

    c++引用详细解说3

    C++是C语言的继承,它可进行过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
    的头像 发表于 02-15 09:43 392次阅读
    <b class='flag-5'>c++</b><b class='flag-5'>引用</b><b class='flag-5'>详细</b><b class='flag-5'>解说</b>3

    C++引用和指针

    之前的文章我们已经介绍了C++中的基本类型如int,bool和double等,除了基本类型C++还有一些更复杂的数据类型复合类型,所谓的复合类型就是通过其他类型定义的类型,本篇文章我们将会着重介绍C++的复合类型
    的头像 发表于 03-17 14:00 476次阅读

    详细解说pcb板表面绝缘层

    详细解说pcb板表面绝缘层
    的头像 发表于 09-28 09:55 2378次阅读