当前位置: 首页 > news >正文

C++引用的详细解释

变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变量起一个别名。

声明如下

1

2

3

4

5

intmain()

{

inta;

int&b = a;

}

1.规则

1.引用没有定义,是一种关系型声明。声明它和原有某一变量的关系。类型与原有类型保持一致,且不分配内存。与被引用的变量有相同的地址。

2.声明的时候必须初始化,一经声明,不可变更。

3.可对引用,再次引用。多次引用的结果,是某一个变量具有多个别名。

4.&符号前面有数据类型时,是引用。其他均为取地址。

1

2

3

4

5

6

7

8

9

10

11

#include <iostream>

usingnamespacestd;

intmain()

{

inta,b;

int&r = a;

int&r = b;//错误,不可更改原有的引用关系

float&rr = b;//错误,引用类型不匹配

cout<<&a<<&r<<endl;//变量与引用具有相同的地址。

int&ra = r;//可对引用更次引用,表示 a 变量有两个别名,分别是 r 和 ra

}

2.应用

1.值作函数参数

1

2

voidswap(inta,intb);//无法实现两数据的交换

voidswap(int*p,int*q);//开辟了两个指针空间实现交换

2.引用作函数参数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <iostream>

usingnamespacestd;

voidswap(int&a,int&b){

inttmp;

tmp = a;

a = b;

b = tmp;

}

intmain(){

inta = 3,b = 5;

cout<<"a = "<<a<<"b = "<<b<<endl;

swap(a,b);

cout<<"a = "<<a<<"b = "<<b<<endl;

return0;

}

c++中引入引用后,可以用引用解决的问题。避免用指针来解决。

3.引用提高

引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得指针的优良特性。所以再对引用取地址,建立引用的指针没有意义

1.可以定义指针的引用,但不能定义引用的引用。

1

2

3

4

5

inta;

int* p = &a;

int*& rp = p;// ok

int& r = a;

int&& rr = r;//error

例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

#include <iostream>

usingnamespacestd;

voidswap(char*pa,char*pb)

{

char*t;

t=pa;

pa=pb;

pb=t;

}

voidswap2(char**pa,char**pb)

{

char*t;

t=*pa;

*pa=*pb;

*pb=t;

}

voidswap3(char*&pa,char*&pb)//指针的引用

{

char*t;

t=pa;

pa=pb;

pb=t;

}

intmain()

{

char*pa="china";

char*pb="america";

cout<<"pa"<<pa<<endl;

cout<<"pb"<<pb<<endl;

//swap(pa,pb);

//swap2(&pa,&pb);

swap3(pa,pb);

cout<<"pa"<<pa<<endl;

cout<<"pb"<<pb<<endl;

return0;

}

2.可以定义指针的指针,不能定义引用的指针。

1

2

3

4

5

inta;

int* p = &a;

int** pp = &p;// ok

int& r = a;

int&* pr = &r;// error

3.可以定义指针数组,但不能定义引用数组,可以定义数组引用。

1

2

3

4

5

inta, b, c;

int* parr[] = {&a, &b, &c};// ok

int& rarr[] = {a, b, c};// error

intarr[] = {1, 2, 3};

int(&rarr)[3] = arr;// ok

4.常引用

const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一些特性。

(1)const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不合法的。

这个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然也不能修改,必须使用 const 引用。实际上,const int a=1; int &b=a;这种写法是不合法的,编译不过。

(2)const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化。

这个是const 引用与普通引用最大的区别。const int &a=2;是合法的。double x=3.14; const int&b=x;也是合法的。

4.常引用原理

const 引用的目的是,禁止通过修改引用值来改变被引用的对象。const 引用的初始化特性较为微妙,可通过如下代码说明

1

2

3

4

5

6

doubleval = 3.14;

constint&ref = val;// int const & int & const ??

double& ref2 = val;

cout<<ref<<" "<<ref2<<endl;

val = 4.14;

cout<<ref<<" "<<ref2<<endl;

上述输出结果为 3 3.14 和 3 4.14。因为 ref 是 const 的,在初始化的过程中已经给定值,不允许修改。而被引用的对象是 val,是非 const 的,所以 val 的修改并未影响 ref 的值,而 ref2 的值发生了相应的改变。

那么,为什么非 const 的引用不能使用相关类型初始化呢?实际上,const 引用使用相关类型对象初始化时发生了如下过程:

1

2

inttemp = val;

constint&ref = temp;

如果 ref 不是 const 的,那么改变 ref 值,修改的是 temp,而不是 val。期望对 ref 的赋值会修改 val 的程序员会发现 val 实际并未修改。

1

2

3

4

5

inti=5;

constint& ref = i+5;

//此时产生了与表达式等值的无名的临时变量,

//此时的引用是对无名的临时变量的引用。故不能更改。

cout<<ref<<endl;

5.const的好处

1,使用 const 可以避免无意修改数据的编程错误。

2,使用 const 可以处理 const 和非 const 实参。否则将只能接受非 const 数据。

3,使用 const 引用,可使函数能够正确的生成并使用临时变量(如果实参与引用参数不匹配,就会生成临时变量)

6.引用的本质浅析

1.大小与不可再引用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

structTypeP

{

char*p;

};

structTypeC

{

charc;

};

structTypeR

{

char& r;//把引用单列出来,不与具体的对象发生关系

};

intmain()

{

printf("%d %d %d\n",sizeof(TypeP),sizeof(TypeC),sizeof(TypeR));

return0;

}

结论:引用的本质是,是对常指针 type * const p 的再次包装。

1

2

3

1、constint*pi 指向常量的指针。

2int*const pi 指针本身是一个常量,称为“指针常量”、“常指针”。

3、constint*const pi 指向常量的指针常量。

总结

本篇文章就到这里了,希望能够给你带来帮助

http://www.jsqmd.com/news/873137/

相关文章:

  • Linux终端字体终极指南:10款精选字体与安装优化全解析
  • 【流体】二维稳态不可压缩层流通道流利用FVM和SIMPLE 解平行板间层流的速度、压力和温度【含Matlab源码 15558期】
  • 为开源项目OpenClaw配置Taotoken作为AI能力供应商的步骤
  • RK3568 SPI驱动实战:MCP2515 CAN控制器寄存器读写原理与优化
  • 18分钟攻破GitHub:TeamPCP供应链攻击全技术解析与防御新范式
  • 如何快速解决Windows 11区域模拟问题:完整API钩子技术指南
  • 为OpenClaw智能体工作流配置Taotoken后端模型
  • S-Video端口ESD防护方案:TVS阵列选型与PCB布局实战指南
  • 芯片设计后期DFT友好ECO:原理、实践与工具选型
  • 全志T113-S3开发板XR829 WiFi蓝牙驱动加载、固件配置与稳定性测试全攻略
  • 西恩士液冷板清洁度萃取设备/清洗机:从源头守护液冷系统“血液”洁净 - 工业设备研究社
  • CVE-2026-9082深度解析:Drupal十年最致命SQL注入,补丁发布3小时即遭全球轰炸
  • 基于RK3399核心板的智能PCR仪开发:从嵌入式系统到高精度温控
  • 为内部培训系统集成Taotoken提供个性化学习内容生成与答疑
  • Photoshop 2026(PSv27.x)详细安装教程与下载地址
  • 【学习笔记】探讨大模型应用安全建设系列8——成果汇报与持续运营
  • 为什么92%的健身APP AI聊天功能被弃用?(行为日志分析+3周A/B测试结论)
  • RK3588蓝牙功能完整测试指南:从驱动到应用实战
  • 嵌入式开发硬件生态构建:MIPI屏、UVC摄像头与4G模块的选型与集成实战
  • S-Video端口ESD防护方案解析:低电容TVS阵列选型与PCB布局实战
  • RK3588开发板蓝牙功能快速测试与配置指南
  • 汽车12V电源保护:TVS二极管选型、应用与EMC测试实战
  • 隐私至上:2026加密不存库PDF转Word工具推荐 - 时讯资讯
  • 2026年企业流量增长视角下档案托管行业GEO优化三家服务商专业分析与选型参考 - 产业观察网
  • 推理 → 行动 → 观察:用 LangChain + Python 实现一个智能体循环
  • 实测SpringBoot集成Taotoken后API调用的延迟与稳定性表现
  • AI智能体Skills设计:从API工具到核心能力的工程实践
  • 汽车12V电源防护:P6KE TVS二极管选型、设计与实战指南
  • Taotoken API Key管理与访问控制功能实际使用反馈
  • 西恩士液冷板清洁度分析仪:AI赋能,让颗粒“显形”更精准 - 工业设备研究社