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

C++从入门到实战(四)C++引用与inline,nullptr

C++从入门到实战(四)C++引用与inline,nullptr


前言

  • 在上一篇博客中,我们深入探讨了 C++ 中两个重要特性:缺省参数与函数重载

上一篇博客地址
https://blog.csdn.net/2402_83322742/article/details/145355328?spm=1001.2014.3001.5501

缺省参数让函数调用更加简便,维护更为轻松;函数重载则增强了代码的可读性和灵活性。通过掌握这两个特性,我们能够编写出更具灵活性和高效性的代码。

  • 这一篇,我们将继续探索 C++ 中另外几个重要的知识点:C++ 引用、inline 关键字以及 nullptr。这些内容将进一步丰富我们对 C++ 语言的理解,为编写更加复杂和高效的程序提供有力支持。

一、C++ 引用

(一)什么是引用

  • 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵,宋江叫 “铁牛”,江湖上人称 “黑旋风”;林冲,外号豹子头;

类型 & 引用别名 = 引用对象;

#include <iostream>
using namespace std;int main()
{int a = 0;int& b = a;int& c = a;//对d相当于还是a的引用int& d = b;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;return 0;
}

上述代码中,b 是 a 的引用,对 b 的操作等同于对 a 的操作,对d相当于还是a的引用

(二)引用的特点

  • 1.必须初始化:引用在定义时必须初始化,即必须指定它是哪个变量的别名。
// 错误示例
int& ref; 
  • 2.一旦初始化后,就不能再引用其他变量
int a = 10;
int b = 20;
int& ref = a;
// ref = b; // 这里不是让 ref 引用 b,而是将 b 的值赋给 ref(也就是 a)
  • 3.一个变量可以有多个引用
#include<iostream>
using namespace std;
int main()
{int a = 10;// 编译报错: “ra”: 必须初始化引用//int& ra;int& b = a;int c = 20;// 这里并非让b引用c, 因为C++引用不能改变指向,// 这里是一个赋值b = c;cout << &a << endl;cout << &b << endl;cout << &c << endl;return 0;
}

(三)引用作为函数参数

引用作为函数参数,可以在函数内部修改传入变量的值,而且相比于指针,代码更加简洁和安全。

void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}int main() {int num1 = 5;int num2 = 10;swap(num1, num2);std::cout << "num1: " << num1 << ", num2: " << num2 << std::endl; return 0;
}

在这个 swap 函数中,通过引用参数直接操作实参,实现了两个数的交换。

(四)引用作为函数返回值

引用也可以作为函数的返回值,这样函数返回的是一个变量的引用,而不是变量的副本。

int arr[5] = {1, 2, 3, 4, 5};
int& getElement(int index) 
{return arr[index];
}int main() 
{getElement(2) = 10; std::cout << "arr[2]: " << arr[2] << std::endl; return 0;
}

(五)引用的使用

  • 1.C++ 中引用在实际应用里,主要用在引用传参和引用做返回值的场景。

引用传参
比如下面这个交换两个数的函数,使用引用传参能直接改变传入的实参值,还减少了数据拷贝,提高效率。而且改变引用对象时,被引用对象也会跟着变。

#include <iostream>
void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}
int main() {int num1 = 5;int num2 = 10;swap(num1, num2);std::cout << "num1: " << num1 << ", num2: " << num2 << std::endl;return 0;
}
    1. 引用传参和指针传参对比

引用传参和指针传参功能差不多,但引用传参用起来更方便。指针传参如下

#include <iostream>
void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}
int main() {int num1 = 5;int num2 = 10;swap(&num1, &num2);std::cout << "num1: " << num1 << ", num2: " << num2 << std::endl;return 0;
}

可以看到,引用传参在函数调用时不需要像指针那样取地址(&),在函数内部使用时也不需要像指针那样解引用(*) 。

  • 3.引用和指针对比

引用和指针在实际编程中都很重要,功能有重叠但各有特点,不能互相替代。C++ 的引用和 Java 的引用区别较大,C++ 引用定义后不能改指向,Java 的可以。

二、Const引用

(1)const 引用是干什么的

const 引用就是加了 “规矩” 的引用。这个 “规矩” 就是:不能通过这个引用去修改它引用的对象。就好像你给一个东西上了把锁,只能看不能动。

(2)引用 const 对象

  • 假如有个变量是 const 的,这就说明这个变量是 “只读” 的,不能被修改。
  • 你要是想用引用去访问它,也得用 const 引用
  • 打个比方,有个宝箱被施了魔法,只能看不能打开(const 变量),你要是想用一个能打开宝箱的钥匙(普通引用)去开它,肯定不行啊,这就违反魔法规则了。代码里就是这样:

const int a = 10;
// 下面这行代码会报错,因为普通引用就像能打开宝箱的钥匙,违反了魔法规则
// int& ra = a; 
const int& ra = a; // 用 const 引用就对啦,就像用了一把只能看宝箱的钥匙

(3)const 引用引用普通对象

  • const 引用也可以引用普通对象

  • 这就好比一个普通人(普通变量),你给他戴上一个 “不能随便乱动” 的帽子(const 引用),虽然他本来可以自由活动,但戴上帽子后就只能乖乖待着了。这其实就是访问权限的缩小,是允许的。

int b = 20;
const int& rb = b; // 给 b 戴上“不能随便乱动”的帽子
// 下面这行代码会报错,因为不能通过 rb 去修改 b
// rb = 30; 

(4)引用和指针的关系

  • 指针和引用就像 C++ 编程世界里的两兄弟,它们既有相似之处,又各有特点

3.1相同点

  • 指针和引用都和变量相关,能用来操作其他变量,功能上有重叠,都可以间接访问别的变量。
  • 比如,你想找到房间里的某样东西,既可以通过知道这个东西所在的房间号(指针指向变量地址),也可以通过记住这个东西的另一个称呼(引用给变量取别名)来找到它。

3.2不同点

  • 1.本质不同

引用:就像是给变量取了个外号,它和被引用的变量其实是同一个东西,不需要额外的存储空间。比如一个人叫张三,大家也叫他小张,小张和张三指的就是同一个人。
指针:是专门用来存放变量地址的,需要开辟额外的存储空间。就好比一个小本子,上面记录着某个东西所在的房间号。

  • 2.初始化要求不同

引用:就像给人取外号,得一开始就明确是给谁取的,所以引用在定义的时候必须进行初始化,之后就不能再换 “对象” 了。比如你一开始给张三取了小张这个外号,就不能再把小张这个外号给别人了。
指针:虽然建议在定义的时候就初始化,但语法上不是必须的。就像小本子你可以先空着,等需要的时候再记录房间号。不过不初始化可能会导致一些问题。

  • 3.指向的灵活性不同

引用:一旦确定引用的对象,就不能再引用其他对象了,它会 “从一而终”。就像外号一旦确定给了某个人,就不能再给别人用了。
指针:可以不断改变指向的对象,就像小本子上可以随时擦掉原来的房间号,写上新的房间号。

  • 4.访问方式不同

引用:可以直接访问指向的对象,因为它就是对象的别名,就像叫小张其实就是在叫张三,能直接找到这个人。
指针:需要通过解引用操作才能访问指向的对象,就像你只知道房间号,得拿着这个号去找到对应的房间,才能拿到里面的东西。

  • 5.sizeof 结果不同

引用:sizeof 得到的是引用类型的大小,也就是被引用对象的大小。就像问小张占多大空间,其实就是问张三占多大空间。
指针:sizeof 得到的是地址空间所占的字节数,在 32 位平台下占 4 个字节,64 位平台下占 8 个字节。不管指针指向的是什么类型的对象,它记录的都是地址,所以大小是固定的,就像小本子不管记录的是哪个房间号,它本身的大小是不变的。

  • 6.安全性不同

引用:很少出现空引用和类似指针的错误情况,使用起来相对更安全,因为它一开始就确定了引用的对象,而且不会改变。就像外号不会叫错人。
指针:容易出现空指针(小本子上没写房间号)和野指针(小本子上写的房间号是错的或者已经无效了)的问题,使用时需要格外小心。

三、nullptr

(一)nullptr 是什么

  • 在 C++ 中,nullptr 是一个关键字,用于表示空指针。
  • 在 C++ 之前,通常用 NULL 来表示空指针,NULL 实际上是一个宏定义,在不同的编译器中可能被定义为 0 或者 (void*)0。而 nullptr 专门用于表示空指针,类型为 std::nullptr_t,可以避免一些与 0 或 NULL 相关的二义性问题。例如:
int* ptr1 = nullptr;
// int* ptr2 = NULL; // 虽然也能表示空指针,但可能存在二义性

(二)nullptr 与 NULL 的区别

类型安全:nullptr 具有明确的类型 std::nullptr_t,而 NULL 可能被定义为 0,这可能导致一些重载函数调用的二义性。例如:

void func(int num) 
{std::cout << "func(int): " << num << std::endl;
}
void func(int* ptr) {std::cout << "func(int*): " << (ptr? "not null" : "null") << std::endl;
}
int main() {func(nullptr); // 明确调用 func(int*)// func(NULL); // 可能会调用 func(int),产生二义性return 0;
}

四、inline 关键字

(一)什么是 inline 函数

  • inline 关键字用于定义内联函数。
  • 内联函数的作用是在编译时,将函数调用处用函数体替换,减少函数调用的开销,提高程序执行效率。
#include <iostream>// 定义一个内联函数,用于计算两个整数的和
inline int add(int a, int b) {return a + b;
}int main() {int x = 3, y = 5;// 调用内联函数int result = add(x, y); std::cout << "The result is: " << result << std::endl;return 0;
}

(二)与C语言宏函数对比

C 语言宏函数:宏函数只是简单的文本替换,不会进行类型检查。

// 定义宏函数
#define ADD(a, b) ((a) + (b))
#define SQUARE(x) ((x) * (x))
// 调用时传入字符串,预处理器仍会进行替换,可能导致运行时错误
char* str = "test";
int res = SQUARE(str); 

C++ 内联函数作为真正的函数,C++ 内联函数会进行严格的类型检查。

inline double square(double num) {return num * num;
}
// 调用时,如果传入整数,会进行隐式类型转换
int result = square(5); 

C++ 内联函数:内联函数是真正的函数,在调试时可以像普通函数一样进行调试,能够方便地设置断点、查看变量值等。而且内联函数的代码结构清晰,易于维护和理解。例如,使用调试器可以单步进入内联函数的代码。
C 语言宏函数:宏函数的调试相对困难,因为预处理器在编译前就完成了文本替换,调试器看到的是替换后的代码,很难直接定位到宏定义的位置。同时,宏函数的代码可能会因为复杂的替换规则而变得难以理解和维护。


以上就是这篇博客的全部内容,下一篇我们将继续探索 C++ 的更多精彩内容。

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

相关文章:

C++从入门到实战(四)C++引用与inline,nullptr

C从入门到实战&#xff08;四&#xff09;C引用与inline&#xff0c;nullptr 前言一、C 引用&#xff08;一&#xff09;什么是引用&#xff08;二&#xff09;引用的特点&#xff08;三&#xff09;引用作为函数参数&#xff08;四&#xff09;引用作为函数返回值&#xff08;…...

Linux库制作与原理:【静态库】【动态库】【目标文件】【ELF文件】【ELF从形成到假造轮廓】【理解链接和加载】

目录 一.什么是库 二.静态库 2.1创建静态库 我们在之前的路径下新建lib使用我们自己的库 2.2 使用makefile生成静态库 三.动态库 3.1动态库生成 3.2动态库使用 3.3库运行搜索路径 四.目标文件 五.ELF文件 六.ELF从形成到加载轮廓 6.1ELF形成可执行 6.2 ELF可执行文…...

项目BUG

项目BUG 前言 我创作这篇博客的目的是记录学习技术过程中的笔记。希望通过分享自己的学习经历&#xff0c;能够帮助到那些对相关领域感兴趣或者正在学习的人们。 项目BUG 1.低频率信号(100k或 200K以下)可以直接用一根导线焊接出几根导线来分几路&#xff0c;高频率信号只能…...

wordpress部署nginx版的

一、通过nginx部署wordpress 1、用yum源安装nginx yum install -y nginx 2、安装php相关软件 前提安装webtatic rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm 通过yum源安装php相关软件 yum -y install php72w php72w-pdo php72w-mysqlnd php72w…...

【鸿蒙Next】优秀鸿蒙博客集锦

鸿蒙基础开发&#xff1a;多文件压缩上传及断点续传_鸿蒙 断点续传-CSDN博客...

【第2章:神经网络基础与实现——2.1 前馈神经网络的结构与工作原理】

老铁们好!今天我们要来一场长达两万字的超详细技术探险,我会像拆解乐高积木一样把前馈神经网络(Feedforward Neural Network)的每个零件摆在台面上,用最接地气的方式让你彻底搞懂这个深度学习基石的工作原理。准备好了吗?我们开始吧! 第一章:神经网络的 “乐高积木” 1…...

python-leetcode-阶乘后的零

172. 阶乘后的零 - 力扣&#xff08;LeetCode&#xff09; class Solution:def trailingZeroes(self, n: int) -> int:count 0while n > 5:n // 5count nreturn count...

Python:学生管理系统(继承性、多态性)。

输出样例如图&#xff1a; 题目内容&#xff1a; 利用继承、多态性等面向对象程序功能编写程序&#xff0c;实现学生管理系统&#xff0c;并包含以下内容&#xff1a; 第一&#xff0c;基类为学生类&#xff0c;并以此派生出本科生类、研究生类。 第二&#xff0c;本科生类包含…...

网络安全RSA加密

网络安全课相关知识&#xff1a; RSA预备知识 1.1 快速幂算法 顾名思义&#xff0c;快速幂就是快速算底数的$n$次幂。其时间复杂度为${\rm{O(log n)}}$&#xff0c;与朴素的$O\left( n \right)$相比&#xff0c;效率有了极大的提高。具体可以参考百度百科&#xff1a;快速幂。…...

Vue学习笔记4

Vue学习笔记 一、自定义创建项目 基于VueCli自定义创建项目架子 二、vuex基本认知 1、vuex概述 是什么&#xff1a;是vue的状态管理工具&#xff08;插件&#xff09;&#xff0c;状态就是数据 大白话&#xff1a;vuex是一个插件&#xff0c;可以帮助我们管理vue通用的数…...

mariadb数据库的安装与部署

1、通过yum源安装mariadb数据库 yum -y install mariadb-server 2、启动mariadb数据库服务 systemctl start mariadb.service 3、配置mariadb数据库全局环境变量 systemctl enable mariadb.service 4、修改mariadb数据库默认密码&#xff0c;数据库默认密码为空 执行…...

单调队列与栈

一.题 1. 思路&#xff1a; 构建小压大的单调递减栈&#xff0c;对于每个栈的元素都进行处理并加到结果上 class Solution { public:int sumSubarrayMins(vector<int>& arr) {int stk[10000000],top 0;long long ans 0;for(int i 0;i<arr.size();i){while(top…...

Matlab 多项式曲线拟合(三维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 对于高维空间曲线的拟合,参数化是一种非常好的方式,可以让我们很容易得到我们想要的目标曲线。 假设给定一组数据点 ( u i ​ , x i ​ ) 、 ( u i ​...

机器翻译同样的文本,是从英语翻译成日语更准确还是中文翻译成日语更准确

在大多数情况下&#xff0c;从英语翻译成日语会比从中文翻译成日语更准确&#xff0c;原因如下&#xff1a; 1. 语言结构的相似性 英语和日语的句子结构更接近&#xff0c;特别是在语法、从句使用、定语位置等方面。例如&#xff0c;日语和英语都使用 SVO 结构&#xff08;主…...

MAC 系统关屏幕后电量消耗极快 Wake Requests

日志为 Wake Requests [*processdasd requestSleepService…info"com.apple.alarm.user-invisible-com.apple.calaccessd… 本人有效方法为&#xff1a; sudo pmset -a hibernatemode 25 sudo pmset -a standby 0 sudo pmset -a autopoweroff 0 会导致hibernatemode 25是…...

golangAPI调用deepseek

目录 1.deepseek官方API调用文档1.访问格式2.curl组装 2.go代码1. config 配置2.模型相关3.错误处理4.deepseekAPI接口实现5. 调用使用 3.响应实例 1.deepseek官方API调用文档 1.访问格式 现在我们来解析这个curl 2.curl组装 // 这是请求头要加的参数-H "Content-Type:…...

提供可传递的易受攻击的依赖项

问题如图所示&#xff1a; 原因&#xff1a;okhttp3.version 3.14.9 版本存在部分漏洞&#xff0c;在 maven 仓库是可以看到的 maven 地址&#xff1a; maven 下图中 Vulnerabilities 即为漏洞 处理&#xff1a;换一个无漏洞的版本即可...

2.14学习记录

Web flag直接读取不就行了&#xff1f; 代码审计&#xff1a; <?php highlight_file(index.php); # 我把flag藏在一个secret文件夹里面了&#xff0c;所以要学会遍历啊~ error_reporting(0); $J1ng $_POST[J]; $Hong $_POST[H]; $Keng $_GET[K]; $Wang $_GET[W]; $d…...

xpath定位--鼠标悬停显示的按钮

UI自动化定位界面元素的过程中&#xff0c;会遇到鼠标悬停才会显示的按钮&#xff0c;鼠标移开就不显示了&#xff0c;无法通过点击它直接定位到元素位置 搜索到这篇文档&#xff0c;办法很好用&#xff0c;特此记录下&#xff1a;chrome调试鼠标悬停后出现的元素_控制台元素调…...

鸿蒙Harmony打包脚本使用整理

最近整理鸿蒙打包相关事宜&#xff0c;遇到很多文档描述不清晰的问题&#xff0c;好在都通过鸿蒙团队的技术支持解决掉了。这里整理一下。 command-line-tools的命令官网基本都有&#xff0c;这里整理几个常用的&#xff0c;还有就是遇到的问题。 hvigorw位置&#xff1a;/comm…...

从GAN到领域自适应:揭秘‘特征对齐’如何让AI模型跨域工作

从GAN到领域自适应&#xff1a;特征对齐如何突破AI模型的跨域瓶颈 想象一下&#xff0c;你花费数月训练的视觉识别模型在实验室测试集上准确率高达98%&#xff0c;但部署到真实场景后性能骤降至60%。这种"实验室到现实"的落差&#xff0c;正是领域自适应(Domain Adap…...

【微电网优化】基于改进自适应粒子群算法的孤岛微电网PID参数优化设计与Matlab仿真

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。&#x1f34e;完整代码获取 定制创新 论文复现点击&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f3…...

安全扫描自动化:构建持续安全检测体系

安全扫描自动化&#xff1a;构建持续安全检测体系 一、安全扫描自动化概述 1.1 安全扫描自动化的定义 安全扫描自动化是指通过工具和脚本自动执行安全检测任务&#xff0c;包括漏洞扫描、代码安全检测、配置安全检查等。它是DevSecOps实践的重要组成部分。 1.2 安全扫描自动化的…...

图像界面编程实现 - 学员管理系统 - 08

图形界面编程实现 - 学员管理系统 - 08 1. 需求描述 开发一个图形界面版的学生管理系统,功能包括: 1.1 添加学员信息 学员信息,要求包括学号、姓名、性别、年龄、联系方式等,其中学号不可重复,姓名和联系方式也不能重复。 1.2 删除学员信息 根据学员的学号,删除某一…...

如何快速解锁QQ音乐加密格式:高效智能的完整解决方案

如何快速解锁QQ音乐加密格式&#xff1a;高效智能的完整解决方案 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac&#xff0c;qmc0,qmc3转mp3, mflac,mflac0等转flac)&#xff0c;仅支持macOS&#xff0c;可自动识别到QQ音乐下载目录&#xff0c;默认转…...

体验Taotoken官方价折扣活动对项目开发成本的实际影响

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 体验Taotoken官方价折扣活动对项目开发成本的实际影响 对于个人开发者和初创团队而言&#xff0c;大模型API的调用成本是项目预算中…...

从‘虚方法表’到性能优化:深入.NET运行时看C# virtual关键字的设计哲学

从‘虚方法表’到性能优化&#xff1a;深入.NET运行时看C# virtual关键字的设计哲学 在C#开发中&#xff0c;virtual关键字看似简单&#xff0c;却承载着面向对象编程中多态性的核心实现。当我们在基类中标记一个方法为virtual时&#xff0c;实际上是在向.NET运行时声明&#…...

[具身智能-636]:什么是语音识别?语音识别的技术过程?语音于语音特征提取?什么环节实现时域到频域的转化?

一、什么是语音识别语音识别 ASR&#xff1a;把人说话的语音声波&#xff08;时域音频&#xff09;&#xff0c;自动转换成文字的技术。本质&#xff1a;时域语音信号 → 机器可懂的语音特征 → 文本。不关心声音多好听&#xff0c;只关心说了什么内容。二、语音识别完整技术流…...

【2026奇点大会闭门报告】:为什么92.7%的AI服务因API契约缺陷在上线30天内降级?

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生API设计规范&#xff1a;2026奇点智能技术大会接口设计最佳实践 AI原生API不再是对传统REST的简单增强&#xff0c;而是以模型能力为第一公民、推理上下文为默认契约、语义完整性为校验基准的全新…...

别再让低通滤波器坑了你!PMSM滑模观测器位置估算的相位补偿实战(附Simulink模型)

永磁同步电机无感控制中的相位补偿实战&#xff1a;从理论到Simulink实现 在永磁同步电机(PMSM)无速度传感器控制领域&#xff0c;滑模观测器因其强鲁棒性成为工程实践中的热门选择。然而&#xff0c;当工程师们兴奋地搭建完仿真模型后&#xff0c;常常会遇到一个令人头疼的现象…...