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

    科技2022-08-12  95

    文章目录

    引用进阶引用的数据类型不同时的特殊情况巧用引用使代码简化巧用引用代替指针引用作为返回值出现的奇怪现象经典面试题:引用和指针的区别?

    引用进阶

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

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

    #include <iostream> using namespace std; int main() { double a = 3.1415926; const int& ra = a; system("pause"); return 0; }

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

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

    根据先前对于引用的认知: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; }

    输出结果:

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

    我们把代码变一变,看看这俩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; }

    输出结果:

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

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

    虽说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; }

    执行结果

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

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

    从变量角度验证:

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

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

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

    第一行汇编代码:将 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)

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

    Processed: 0.011, SQL: 8