当前位置: 代码网 > it编程>编程语言>C/C++ > C++中的引用和inline 和 nullptr全面解析

C++中的引用和inline 和 nullptr全面解析

2026年05月11日 C/C++ 我要评论
一.引用1.1引用的概念与定义引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。⽐如:⽔壶传中李逵,宋江叫"铁⽜&

一.引用

1.1引用的概念与定义

引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。⽐如:⽔壶传中李逵,宋江叫"铁⽜",江湖上⼈称"⿊旋 ⻛";林冲,外号豹⼦头;

类型& 引⽤别名=引⽤对象

c++中为了避免引⼊太多的运算符,会复⽤c语⾔的⼀些符号,⽐如前⾯的>,这⾥引⽤也和取 地址使⽤了同⼀个符号&,⼤家注意使⽤⽅法⻆度区分就可以。(吐槽⼀下,这个问题其实挺坑的,个 ⼈觉得⽤更多符号反⽽更好,不容易混淆

从这里我们可以看出,i和j的地址是一样的,说明他们指向同一块空间,引用不会开辟新空间

1.2 引⽤的特性

1.引⽤在定义时必须初始化

2.⼀个变量可以有多个引⽤

3. 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体

这里我们可以看出,引用b指向了a,说明是给a取了别名;若要让b在指向d,d现在是20,这里就是赋值的意思,将20赋值给b,而b又是a的别名,所以a的值也发生了改变

4.别名++,其存在的变量也++

1.3 引⽤的使⽤

1.3.1引用传参的使用

1. 引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被引⽤对象。

2.引⽤传参跟指针传参功能是类似的,引⽤传参相对更⽅便⼀些。

如果使用指针来实现两个数的交换,首先swap1中的ab需要开辟一个空间来指向x1,y1的地址,需要拷贝;

若用引用的话,只是给x2,y2起别名,ab发生改变,x2,y2也同时发生改变,但这种情况不会开辟新空间,不需要拷贝优于指针

上面的图返回的是临时变量,是一个值,需要存储起来,不能直接进行修改;

下面的图返回的是它的引用,可以进行直接修改

3.引⽤返回值的场景相对⽐较复杂,我们在这⾥简单讲了⼀下场景,还有⼀些内容后续类和对象章节 中会继续深⼊讲解。

4.引⽤和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。c++的引⽤跟其他 语⾔的引⽤(如java)是有很⼤的区别的,除了⽤法,最⼤的点,c++引⽤定义后不能改变指向, java的引⽤可以改变指向。

5.⼀些主要⽤c代码实现版本数据结构教材中,使⽤c++引⽤替代指针传参,⽬的是简化程序,避开 复杂的指针,但是很多同学没学过引⽤,导致⼀头雾⽔。

1.3.2传引用返回

再说传引用返回,这里返回的是ret的别名

但是这样的传引用返回的行为,本质上是非常危险的,func函数结束之后,func栈帧就销毁了,但是tmp依旧是ret这块空间的别名,tmp依旧在访问ret,就相当于野指针的访问。此时返回的就不一定是0了,也有可能是随机值

正确传引用返回:

如图出了作用域,func1结束,ret还在,此时被static修饰的ret就不存在func1的栈帧之中了

1.4 const引用


1.可以引用一个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。

   如图,如果a被const修饰了,引用就不能使用了,此时a不能改变,但是b是a的别名,可以改变a,这就是一个权限放大的场景,权限是不能放大的,想要正常引用就要权限移b也要被const修饰

用const修饰a,a只能读不能写;而b是a的引用,没有用const,那么b既能读又能写,放大了a的权限

这样写才是正确的,a和b都只能读不能写。

a可读可写,但是引用后只能读不能写,这样是正确的,缩小了权限

2.不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场 景下a*3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对 象存储中间值,也就是说,rb和rd引⽤的都是临时对象,⽽c++规定临时对象具有常性,所以这⾥ 就触发了权限放⼤,必须要⽤常引⽤才可以。

  • int&非常量左值引用,它只能绑定到一个可修改的左值(即有内存地址的变量)。
  • a * 3 是一个临时右值(计算结果是一个没有名字的临时值,没有持久的内存地址),无法被非常量左值引用绑定。

正确写法是在引用前面加上const修饰,只能读。

  • double d = 12.34;定义了一个 double 类型变量 d,值为 12.34
  • int i = d;
    • double 类型的 d 隐式转换为 int,截断小数部分,i 的值为 12
    • 这是直接赋值,i 是一个独立的新变量,和 d 共享内存。
  • const int& ri = d;
    • 试图将 double 类型的 d 绑定到 const int& 类型的引用。
    • 由于类型不匹配,编译器会生成一个临时的 int 类型对象,将 d 截断为 12 存入该临时对象,然后让 ri 绑定到这个临时对象。
    • 这就是图中标注的「临时对象」:它是一个匿名的、生命周期被 const int& 延长的临时变量,ri 并不直接引用 d,而是引用这个临时对象。

1.5指针与引用的关系

对比维度引用(reference)指针(pointer)
本质概念变量的别名,不单独占用内存空间存储变量的内存地址,需要占用内存空间
初始化要求定义时必须初始化,且必须绑定到一个已存在的对象建议初始化,但语法上不强制,可以先声明后赋值
指向关系初始化后无法再更改绑定对象,始终指向最初绑定的变量可以随时改变指向,指向不同的变量或空地址
访问方式直接使用引用名访问目标对象,无需解引用需要通过 * 解引用操作符才能访问目标对象
sizeof 含义sizeof(引用) 结果为所引用类型的大小(如 sizeof(int&) = 4)sizeof(指针) 结果为地址空间的字节数(32 位平台为 4 字节,64 位平台为 8 字节)
安全性不存在空引用、野引用问题,使用相对更安全容易出现空指针、野指针问题,使用时需额外判断合法性
典型用途函数参数传递(避免拷贝)、函数返回值(保证非空)动态内存管理、数组遍历、复杂数据结构(链表 / 树)的节点操作

二、inline

先看一下宏常见的问题

看似没有问题,但这个宏在另一种场景下就又不对了

所以可以看出宏函数很容易出现问题,很复杂,还不能调试

所以c++之父就搞了个内联出来

写个函数是不容易写错的,但写个宏函数很容易写错
宏函数的优点就是可以提高效率,适用于高频调用的小函数,预处理阶段宏会替换,不建立栈帧,而且宏甚至可以传类型

c++中内联就是用来替换宏的

用inline修饰的函数叫做内联函数,编译时c++编译器会在调用的时候展开(不是把函数部分的代码直接放到主函数处,而是把函数地方的逻辑经过一定的处理,经过编译器自己分析,用于主函数处)内联函数,这样调用内联函数就不需要建立栈帧了,就可以提高效率
inline对于编译器而言只是一个建议,也就是说,你加了inline编译器也可以选择在调用的地方不展开,不同编译器关于inline什么情况展开各不相同,因为c++标准没有规定这个。inline适用于频繁调用的短小函数,对于递归函数,代码相对多一些的函数,加上inline也会被编译器忽略。

三、nullptr

nullptr是c++11的一个关键字,是用来替代c语言的null的

null实际上是一个宏,在传统的c头文件(stddef.h)中,可以看到如下代码:

#ifndef null
    #ifdef __cplusplus
        //c++中的null被替换为0,默认为整型
        #define null    0
    #else
        //c语言中的null也被替换为0,但是被强制类型转换为(void*)
        #define null    ((void *)0)
    #endif
#endif

c++中null可能被定义为字面常量0,或者c中被定义为无类型指针(void * )的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,本想通过f(null)调用指针版本的f(int * )函数,但是由于null被定义成0,调用了f(int x),因此与程序的初衷相悖。f((void* )null);调用会报错

在c++之中,void* 给int* 是需要强制类型转换的
c++11中引用nullptr,nullptr是一个特殊的关键字(就相当于语法层在编译的时候就特殊解决该问题了),nullptr是一种特殊类型的字面量,它可以转换成任意其它类型的指针类型(值还为0)。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式转换为指针类型,而不能被转换为整数类型。

到此这篇关于c++中的引用和inline 和 nullptr全面解析的文章就介绍到这了,更多相关c++引用和inline 和 nullptr内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com