【C++】一篇文章搞定引用进阶

引用进阶

引用的数据类型不同时的特殊情况

看下面代码,观察情况想一想?

#include <iostream>
using namespace std;

int main()
{
    
    
    double a = 3.1415926;
    const int& ra = a;

    system("pause");
    return 0;
}

image.png

  • 我们常说:一个变量的引用就相当于给这个变量取别名,这个引用变量和变量表示同一块内存空间,其地址相同,内容相同,操作引用就相当于操作原变量。

但是从上述代码及现象中可以看出:引用和变量都有各自的空间,这是为什么?

image.png

  • 根据先前对于引用的认知:ra和a的地址不一样,说明ra并不是a的别名,即ra不是a的引用

  • 原因:其实是因为当ra去引用a时,编译器发现,ra和a的数据类型不一致,于是编译器就创建了一块临时空间给ra引用,这块临时空间中的数据无法修改,具有常量特性,这也就是为什么ra需要加上const修饰,如果没有const限定就无法通过编译。

启示:引用变量数据类型和被引用变量数据类型必须相同哦!

巧用引用使代码简化

通过对比两句代码观察引用的好处

#include <iostream>
using namespace std;
struct A
{
    
    
    int a;
    int b;
    struct B
    {
    
    
        int c;
        int d;
        struct C{
    
    
            int e;
            int f;
        };
        C strC;
    };
    B strB;
};

int main()
{
    
    
    A a;
    a.strB.strC.e = 10;

    int& re = a.strB.strC.e;
    re = 20;

    system("pause");
    return 0;
}

这里将a.strB.strC.e被一个引用变量re代替,使得代码简化

巧用引用代替指针

实现两个数的交换

void swap(int& a, int& b)
{
    
    
    int temp = a;
    a = b;
    b = temp;
}

这里引用的作用一级指针作用有异曲同工之妙

引用作为返回值出现的奇怪现象

#include <iostream>
using namespace std;

int& add(int a, int b)
{
    
    
    int sum = a + b;
    return sum;
}

int main()
{
    
    
    int& sum = add(1, 2);
    cout << "sum = " << sum << endl;
    
    add(2, 3);
    cout << "sum = " << sum << endl;
    
    add(3, 4);
    cout << "sum = " << sum << endl;
    
    system("pause");
    return 0;
}

输出结果:

image.png

这是为啥呢??????咋还会变呢???????

image.png

我们把代码变一变,看看这俩sum会不会有什么关系呢?

#include <iostream>
using namespace std;

int& add(int a, int b)
{
    
    
    int sum = a + b;
    cout << "<add> &sum = " << &sum << endl;
    return sum;
}

int main()
{
    
    
    int& sum = add(1, 2);
    cout << "<main> &sum = " << &sum << endl;

    system("pause");
    return 0;
}

输出结果:

image.png

嗷嗷嗷!!!!!原来他们是同一块内存呀!!!!(吓到模糊)

image.png

正常来说:一个函数中的局部变量就是在函数执行结束时其生命结束,变量所在的那块地址上面的数据已经是无效数据,那块地址已经是非法空间了

虽说main函数中的引用变量指向的是add函数中局部变量sum开辟的空间,但此块空间是非法空间,访问了还未被清除的无效数据

如何触发清理无效数据呢?只需要一句输出语句即可,如下面代码:

int& add(int a, int b)
{
    
    
    int sum = a + b;
    return sum;
}

int main()
{
    
    
    int& sum = add(1, 2);
    add(3, 4);

    cout <<  endl;
    cout << "sum = " << sum << endl;
    
    system("pause");
    return 0;
}

执行结果

image.png

此时非法空间中的无效数据已经变成了随机值

经典面试题:引用和指针的区别?

从变量角度验证:

    int a = 100;

    int* pa = &a;
    *pa = 10;

    int& ra = a;
    ra = 10;

从表面上并不能看出啥,我们可以看看底层汇编代码是如何解释这两个东西的?

image.png

从汇编代码中我们可以看出:

第一行汇编代码:将 a的地址 放入 eax/edx寄存器中

第二行汇编代码:将 eax/edx寄存器中的数据 放入 pa/ra空间中

第三行汇编代码:将 pa/ra空间中的数据 放入 ecx/eax寄存器中

第四行汇编代码:将 0A这个16进制数据 放入 ecx/eax寄存器中

结论:引用和指针的底层实现方式基本一样

从函数角度验证:

void swap(int* a, int* b)
{
    
    
    int temp = *a;
    *a = *b;
    *b = temp;
}
void swap(int& a, int& b)
{
    
    
    int temp = a;
    a = b;
    b = temp;
}

int a = 1, b = 2;

swap(&a, &b);   //调用swap(int* a, int* b)

swap(a, b);     //调用swap(int& a, int& b)

image.png

分别用引用和指针实现的swap函数也可以看出:引用和指针一模一样哦!

猜你喜欢

转载自blog.csdn.net/weixin_45437022/article/details/108927851