设为首页收藏本站
查看: 216|回复: 2

6.《剑指C++》之从C到C++(6)

[复制链接]
  • TA的每日心情
    擦汗
    昨天 08:01
  • 签到天数: 760 天

    [LV.10]以坛为家III

    发表于 2020-6-12 09:30:10 | 显示全部楼层 |阅读模式
    本帖最后由 御天行 于 2020-6-12 19:28 编辑

    ======《剑指C++系列》:总目录======

    本讲主要介绍:C++之引用(上)
    1.定义:
    变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变量起别名。
    声明如下:
    1. int a;
    2. int ra=&a;
    复制代码

    2.引用的规则:
    1.引用,是一种关系型的声明,而非定义。不能独立存在,必须初始化,且与原类型保持一致,且不分配内存
    2.声明关系,一经声明,不可变更。
    3.可对引用,再次引用。多次引用的结果,是某一变量具有多个别名,多个别名词。是平行关系。
    4.辨别引用与其他,&符号前有数据类型时,是引用,其他皆为取地址或按位"与"。
    实验1:引用规则初探
    1. #include<iostream>
    2. using namespace std;

    3. int main(void){

    4.     int a,b;
    5.     int &ra = a;         //此时操作ra,等价于操作变量a
    6.     //int &ra = b;         //error:不可对已有的引用(别名)进行更改,实之再成为其他变量的别名
    7.     //float &rb = b;       //error:引用类型不匹配

    8.     int &raa = a;
    9.     int &raaa = ra;      //可以对引用再次引用,此时操作raaa也等价于操作变量a

    10.     return 0;
    11. }
    复制代码

    3.应用:
    引用的真正目的,就是取代指针传参。C++引入引用后,可以用引用来解决问题。避免了用指针来解决问题(指针过于强大,是一把双刃剑,能少用则少用)
    接下来看一个在C语言讲解指针时,一个熟悉的交换案例:
    实验2:通过传引用和传指针解决数值交换问题
    1. #include<iostream>
    2. using namespace std;

    3. void mySwap1(int *a, int *b){
    4.     int tmp;
    5.     tmp = *a;
    6.     *a = *b;
    7.     *b = tmp;
    8. }

    9. void mySwap2(int &a, int &b){
    10.     int tmp;
    11.     tmp = a;
    12.     a = b;
    13.     b = tmp;
    14. }

    15. int main(void){

    16.     int x=10, y=20;
    17.     cout<<"Before swap:"<<endl;
    18.     cout<<"x="<<x<<" y="<<y<<endl;

    19.     mySwap1(&x,&y);
    20.     cout<<"After mySwap1():"<<endl;
    21.     cout<<"x="<<x<<" y="<<y<<endl;

    22.     mySwap2(x,y);
    23.     cout<<"After mySwap2():"<<endl;
    24.     cout<<"x="<<x<<" y="<<y<<endl;

    25.     return 0;
    26. }
    复制代码

    运行结果如下:

    由本实验可知,通过传引用,也可以等价于传指针,实现的数值的交换。
    引用的从宏观上可以理解为,扩展了变量的作用域,传参后,就像在本地解决问题一样。避免了传 n 级指针,解决 n-1 级指针的问题,即平级内解决问题。
    4.引用提高篇
    1.指针的引用--有,引用的指针--无
    引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得了指针的优良特性。所以再对引用取地址,建立引用的指针没有意义。

    我们再来分析一个经典案例:
    1. #include<iostream>
    2. using namespace std;
    3. void Swap1(char * p, char * q){
    4.     char *t = p;
    5.     p = q;
    6.     q = t;
    7. }

    8. void Swap2(char **p, char **q){
    9.     char *t = *p;
    10.     *p = *q;
    11.     *q = t;
    12. }

    13. void Swap3(char * &rp, char * &rq){
    14.     char *t = rp;
    15.     rp =rq;
    16.     rq =t;
    17. }

    18. int main(void){

    19.     char * m = "Hellow";
    20.     char * n = "Honker";

    21.     cout<<"Before Swap:"<<endl;
    22.     cout<<"m->"<<m<<endl;
    23.     cout<<"n->"<<n<<endl;

    24.     //Swap1(m,n);
    25.     //Swap2(&m,&n);
    26.     //Swap3(m,n);

    27.     cout<<"Swap():"<<endl;
    28.     cout<<"m->"<<m<<endl;
    29.     cout<<"n->"<<n<<endl;


    30.     return 0;
    31. }
    复制代码

    分别调用:Swap1()、Swap2()、Swap3(),可得出以下运行结果:
    调用Swap1():

    调用Swap2():

    调用Swap3():

    对这几个函数进行分析(关于内存四区一级指针传参二级指针传参的相关内容,已在《C进阶系列》中详细探究,这里只做简要分析):
    1. void Swap1(char * p, char * q){
    2.     char *t = p;
    3.     p = q;
    4.     q = t;
    5. }
    复制代码

    1. void Swap2(char **p, char **q){
    2.     char *t = *p;
    3.     *p = *q;
    4.     *q = t;
    5. }
    复制代码

    1. void Swap3(char * &rp, char * &rq){
    2.     char *t = rp;
    3.     rp =rq;
    4.     rq =t;
    5. }
    复制代码

    虽然Swap3()传入的还是一级指针,但这里传入的是指针的引用,就像在全局范围内操作指针中存放内容,在这里实现了等价于二级指针的交换功能。再一次验证了引用的意义就是为了"平级内解决问题"
    2.指针的指针--有,引用的引用--无
    指针的指针,即二级指针。C++为了避免 C 语言设计指针的"失误",避免了引用的引用这种情况。由此,也避免了引用的引用的引用的.....的引用的情况,这种可穷递归的设计本身就是有问题的。--《C++基础与提高.第4版》如下语法:
    1. //允许建立指针的指针(多级指针)
    2.     int * p;
    3.     int **q = &p;
    复制代码
    1. //不允许建立引用的引用
    2.     int a;
    3.     int &ra = a;
    4.     int &&rrra =a;    //引用的引用,是不存在的,C++11 赋于它新的意义,右值引用
    复制代码

    3.指针数组--有,引用数组--无
    数组名,本身是首元素的地址,若首元素是引用的话,数组名,就成了,引用的指针,与前面讲的不符,即不存在引用的指针。

    4.数组的引用
    数组名,本质是一个常量指针,对于指针是可以取引用的,所以数组的引用是存在的,如下:
    1. #include<iostream>
    2. using namespace std;

    3. int main(void){

    4.     int array[5];

    5.     //数组名实质上就是一个常量指针
    6.     int *const &pr = array;
    7.     printf("sizeof(pr) = %d\n",sizeof(pr));

    8.     int (&ra)[5] = array;
    9.     printf("sizeof(ra) = %d\n",sizeof(ra));
    10.     printf("sizeof(array)=%d\n",sizeof(array));

    11.     return 0;
    12. }
    复制代码

    运行结果如图:

    上一篇:5.函数的默认参数
    下一篇:7.C++之引用(下)

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
  • TA的每日心情
    开心
    昨天 12:21
  • 签到天数: 1463 天

    [LV.10]以坛为家III

    发表于 2020-6-12 13:01:00 | 显示全部楼层
    感谢楼主无私奉献,期待楼主更多精彩!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 2020-7-1 10:31:42 来自手机 | 显示全部楼层
    收藏了 感谢楼主分享
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    站长推荐 上一条 /3 下一条

    红盟社区--中国红客联盟 

    Processed in 0.065068 second(s), 16 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    Powered by HUC © 2001-2017 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表