欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > c/c++ >内容正文

c/c++

想和高手侃侃而谈C++引用?看这一篇就够了【C++引用】

发布时间:2025/3/20 c/c++ 42 豆豆
生活随笔 收集整理的这篇文章主要介绍了 想和高手侃侃而谈C++引用?看这一篇就够了【C++引用】 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

  • 定义
  • 应用
  • 存在对指针取引用
  • 不存在对引用取地址
  • 存在指针的指针,不存在引用的引用
  • 存在指针数组,不存在引用数组
  • 数组的引用
  • 常引用
  • 常引用的特性
  • 临时对象的常引用
    • 类型不同的变量常引用本质剖析
  • 在能够使用 const 的地方就使用 cosnt
  • 引用的本质
    • 引用的大小
    • 引用的类型
    • 结论
    • 反汇编比对指针和引用
      • 源代码
      • 汇编代码比对结果
      • 结论

定义

变量名本身是一段内存的引用,也就是别名。
引用是为已有变量起别名。

int a; int &ra = a;

引用是声明关系,不分配内存空间(宏观)。
引用必须初始化,不能独立存在。
与被别名的变量具有相同数据类型。

代码演示:

#include <iostream>using namespace std;int main() {int a = 100;int& ra = a;cout << "a = " << a << endl;cout << "ra = " << ra << endl;cout << "&a = " << &a << endl;cout << "&ra = " << &ra << endl;cout << "sizeof(a)= " << sizeof(a) << endl;cout << "sizeof(ra) = " << sizeof(ra) << endl;return 0; }

运行结果:

值相等,地址相等,大小相等,证明了引用在内存中的别名关系。

可以对引用再次取引用,对一个变量建立多个引用,多个引用之间是等价关系。
代码演示:

#include <iostream>using namespace std;int main() {int a = 100;int& ra = a;int& rb = a;int& rc = rb;int& rd = rc;cout << "a = " << a << endl;cout << "ra = " << ra << endl;cout << "rb = " << rb << endl;cout << "rc = " << rc << endl;cout << "rd = " << rd << endl;cout << "&a = " << &a << endl;cout << "&ra = " << &ra << endl;cout << "&rb = " << &rb << endl;cout << "&rc = " << &rc << endl;cout << "&rd = " << &rd << endl;cout << "sizeof(a) = " << sizeof(a) << endl;cout << "sizeof(ra) = " << sizeof(ra) << endl;cout << "sizeof(rb) = " << sizeof(rb) << endl;cout << "sizeof(rc) = " << sizeof(rc) << endl;cout << "sizeof(rd) = " << sizeof(rd) << endl;return 0; }

运行结果:

应用

取代指针传参。
C++可以用引用解决的问题,避免用指针来解决。

代码演示;

#include <iostream>using namespace std;void swapByValue(int a, int b) {int tmp;tmp = a;a = b;b = tmp; }void swapByPtr(int* a, int* b) {int tmp;tmp = *a;*a = *b;*b = tmp; }void swapByRef(int& a, int& b) {int tmp;tmp = a;a = b;b = tmp; }int main() {int a = 3, b = 5;cout << "a = " << a << " b = " << b << endl;swapByRef(a, b);cout << "a = " << a << " b = " << b << endl;return 0; }

运行结果:

引用的从宏观上可以理解为:扩展了变量的作用域,传参后,就像在本地解决问题一样。
把一个变量以引用的方式传到另一个作用域,等价于扩展了该变量的作用域。
避免了传 n 级指针,解决 n-1 级指针的问题,即平级内解决问题。

存在对指针取引用

代码演示:

#include <iostream> using namespace std;void swapByRef(char * & a, char * & b) {char * tmp;tmp = a;a = b;b = tmp; }int main() {char* p = "hello";char* q = "world";cout << "p = " << p << " q = " << q << endl;swapByRef(p, q);cout << "p = " << p << " q = " << q << endl;return 0; }

运行结果:

不存在对引用取地址

引用的本质:对指针的包装,避免使用裸露的指针。
设计思想:C++避免对引用再次拆封。
代码演示:

#include <iostream> using namespace std;int main() {int a;int* p = &a;int* & pr = p;int& ra = a;int& * rpa = &ra;return 0; }

编译器报错:不允许使用指向引用的指针。

存在指针的指针,不存在引用的引用

指针的指针,即二级指针。
C++为了避免 C 语言设计指针的"失误",避免了引用的引用这种情况,也避免了引用的引用的引用的…的引用的情况。
这种可穷递归的设计本身就是有问题的。

代码演示:存在指针的指针

#include <iostream> using namespace std;int main() {int a;int* p = &a;int** pp = &p;int*** ppp = &pp;int**** pppp = &ppp;//无穷无尽return 0; }

代码演示:不存在引用的引用

#include <iostream> using namespace std;int main() {int a;int & p = a;int&& pp = p; //刹车return 0; }

存在指针数组,不存在引用数组

数组名,本身是首元素的地址,若首元素是引用的话,数组名就成了引用的指针,与上面说过的不符,即不存在引用的指针。
代码演示:存在指针数组

#include <iostream> using namespace std;int main() {int a, b, c;int* pArr[] = {&a, &b ,&c};return 0; }

pArr 代表首元素地址,首元素是 &a 指针,则 pArr 是二级指针。

代码演示:不存在引用数组

#include <iostream> using namespace std;int main() {int a, b, c;int & pArr[] = {a, b ,c};return 0; }

编译器报错:

pArr 代表首元素地址,首元素是变量名a(可以将a理解为对内存的引用),上面说过不允许对引用取地址。

数组的引用

代码演示:

#include <iostream> using namespace std;int main() {//数组名的两重性://1:代表整个数组。//2:代表首元素地址。int array[5] = {1,2,3,4,5};int* const & pr = array; //int* const &cout << pr << endl;cout << array << endl;cout << "sizeof(pr) = " << sizeof(pr) << endl;cout << "sizeof(array) = " << sizeof(array) << endl;for (int i = 0; i < 5; i++){cout << pr[i];}cout << endl;int(&ra)[5] = array;cout << ra << endl;cout << array << endl;cout << "sizeof(ra) = " << sizeof(ra) << endl;cout << "sizeof(array) = " << sizeof(array) << endl;for (int i = 0; i < 5; i++){cout << ra[i];}cout << endl;return 0; }

运行结果:

常引用

C++中 const 定义的变量称为常变量。
const 修饰的变量,有着变量的形式,常量的作用,用作常量,常用于取代#define 定义的宏常量。
#define 宏定义在预处理阶段替换,const 常量在汇编阶段替换。

常引用的特性

const 的本意,即不可修改。所以,const 对象,只能声明为 const 引用,使其语义保持一致性。

no-const 对象,既可以声明为 const 引用,也可以声明为 no-const 引用。
声明为 const 引用,则不可以通过 const 引用修改数据。

代码演示:

#include <iostream> using namespace std; int main() {const int val = 10;//int& rv = val; //err类型不等价const int &rv2 = val;//类型等价int data = 666;int& rd = data;const int& rd2 = data;//非const 对象生命为 const 引用//rd2 = 333; 不可修改cout << "data = " << data << " rd = " << rd << " rd2 = " << rd2 << endl;data = 999; cout << "data = " << data << " rd = " << rd << " rd2 = " << rd2 << endl;return 0; }

运行结果:

临时对象的常引用

临时对象:不可以取地址的对象。

临时对象:

  • CPU中计算产生的中间变量。
  • 常量。
  • 表达式。
  • 函数返回值。
  • 类型不同的变量。
  • 代码演示:临时对象的常引用

    #include <iostream>using namespace std;//临时变量 即不可取地址的对象int foo() {int a = 66;return a; }int main() {//常量const int& cc = 55;cout << "cc = " << cc << endl;//表达式int a = 3;int b = 5;const int& ret = a + b;cout << "ret = " << ret << endl;//函数返回值const int& ra = foo();cout << "ra = " << ra << endl;//类型不同的变量double d = 100.12;const int& rd = d;cout << "d = " << d << endl;cout << "rd = " << rd << endl;return 0; }

    运行结果:

    临时对象的常引用本质:产生中间变量。

    类型不同的变量常引用本质剖析

    代码演示:

    #include <iostream>using namespace std;int main() {double d = 3.14;//int & t = d; err 类型不等价const int& rd = d; //产生中间变量cout << "d = " << d << endl;cout << "rd = " << rd << endl;d = 4.14;cout << "d = " << d << endl;cout << "rd = " << rd << endl;return 0; }

    运行结果:

    本质上 const 引用,引用了一个不可改变的临时变量,

    const int tmp = data; const int & rd = tmp;

    此时,我们改变了 data 的值,临时变量 tmp 的值并没有发生改变。

    在能够使用 const 的地方就使用 cosnt

    好处:

  • 避免无意修改数据的编程错误。
  • 使用 const 处理 const 和 非cosnt 。否则将只接受 非const数据。
  • 使用 cosnt引用,可使函数能够正确的生成并使用临时变量。(实参与引用参数不匹配,就会产生临时变量。)
  • 引用的本质

    引用的本质:C++对指针的包装,引用即指针。

    引用的大小

    代码演示;

    #include <iostream>using namespace std;struct TypeP {char* p; };struct TypeC {char c; };struct TypeR {char& r; };int main() {cout << "sizeof(TypeP) = " << sizeof(TypeP) << endl;cout << "sizeof(TypeC) = " << sizeof(TypeC) << endl;cout << "sizeof(TypeR) = " << sizeof(TypeR) << endl;return 0; }

    运行结果:

    引用的类型

    C++中只有 const 类型的数据,要求必须初始化。
    引用也必须要初始化,所以引用是 const 修饰的指针,一经声明,不可修改。引用的内容可以修改。所以是:type* const p

    结论

    引用的本质是 const 类型的指针,即 type* const p。
    引用是对指针的封装。
    从微观角度来说,引用至少需要分配一个指针类型大小的内存空间。

    反汇编比对指针和引用

    源代码

    代码演示:

    #include <iostream>using namespace std;void swapPtr(int* p, int* q) {int t = *p;*p = *q;*q = t; } void swapRef(int& p, int& q) {int t = p;p = q;q = t; } int main() {int a = 3; int b = 5;swapRef(a, b);swapPtr(&a, &b);return 0; }

    汇编代码比对结果

    结论

    对同一个功能相同的程序,分别采用了指针和引用的两种方式来进行编写,汇编得到的结果一致。
    证明:引用的本质是对指针的封装。

    总结

    以上是生活随笔为你收集整理的想和高手侃侃而谈C++引用?看这一篇就够了【C++引用】的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。