C++11—右值引用
目录
简介
左值和右值
左值
右值
右值引用
生命周期
引用折叠
实际应用
移动语义
移动构造函数
移动赋值运算符
完美转发
简介
之前我们曾学习过引用叫左值引用,但那是C++98的,在C++11中新增了一种引用叫右值引用。右值引用主要用于支持移动语义和完美转发。从而可以更高效地管理资源,减少不必要的复制操作。
左值和右值
左值
左值是指可以取地址的表达式。它通常出现在赋值操作符左侧。
下面是它的几个特性:
- 可寻址性:左值在内存中有明确的地址,即可以取地址。
- 持久性:左值通常指向内存中的持久对象,这些对象在表达式结束后仍然存在。
- 可变性:左值可以被重新赋值,即可以改变其存储的值。
例:
int a = 0;
int* p = new int[10];
上面的a就是左值 ,因为它有持久的内存地址,并且可以被后续的代码访问和修改。*p同理。
右值
右值是指不可以取地址的临时对象,它通常出现在表达式的结果。
下面是它的几个特性:
- 不可寻址性:右值通常没有持久的内存地址,即不可以取地址。
- 短暂性:右值通常表示的是一些临时的值,这些值在表达式结束后就会被销毁。
例:
int a = 0;
int b = 1;
int c = a + b;
上面的0,1就是右值 ,因为它是一个字面常量,没有持久的内存地址。a + b也是右值,因为它是表达式的结果,没有持久的内存地址。
常见的右值有:
- 字面常量,如整数常量(如
42
)、字符常量('a')等。
- 无引用的函数返回值。
- 表达式的结果,如算术表达式(如1+1)、逻辑表达式(如a||b)、关系表达式(如a>b)。
想区分它们也很简单只要能取地址就是左值,不能取地址就是右值。
右值引用
右值引用的表示如下:
int&& a = 1;
右值引用和左值引用没有什么区别都是起别名,从汇编层来看它们都是用指针来实现的。只不过一个是给右值起别名一个给左值。
虽然说右值引用不能引用左值,但是可以通过std::move函数来实现。该函数可以让左值变右值,本质上是通过强制类型转换(使用该函数要小心原对象会变成不确定状态,原因一会儿在解答)。
int a = 1;
int&& ra = move(a);
同样的左值引用也可以引用右值在前面加const,即const左值引用。当const左值引用绑定右值时,编译器通常会创建一个临时对象,并将右值的内容复制到该临时对象中。又因为临时对象有只读性,被const修饰后的对象也只具有只读性。这是权限的平移,所以可以这样是OK的。
const int& a = 1;
注意:一个右值被右值引用绑定后,右值引用变量表达式的属性是左值!就像上面的ra虽然它是一个右值引用,但它自身作为一个变量是左值。
生命周期
大家可能发现了当一个临时的或匿名的对象被右值引用后,它好像不仅仅可以出现在该行,其它行好像也可以出现。事实上当一个对象被右值引用后它的生命周期就被延长了。不仅仅是右值引用,const左值引用的对象也是可以实现的只不过内容无法修改。例如:
int main()
{string&& str1 = string("ha");str1 += "ha";cout << "str1: " << str1 << endl;const string& str2 = string("xi");cout << "str2: " << str2 << endl;return 0;
}
引用折叠
它的规则是:右值引用的右值引用折叠成右值引用,其他组合均折叠成左值引用。简单来说如果是两个都是右值引用那就折叠成右值引用,其他就都是左值引用。这主要是为了实现万能引用。示例:
template<class T>
void Test(T&& x)
{//...
}
注意上面的参数虽然是通过右值引用传递的,因为它是一个模板所以这是一个万能引用。不太懂的可以先往下看。当用下面代码调用时:
Test(10);
由于Test函数模板的参数是T&&,这里发生了模板参数推导即转发引用。简单来说当传递一个左值给接受T&&参数的函数模板时,编译器会推导T为左值引用类型;右值即非引用类型。
在这种情况下,编译器会T推导为int(因为10是int类型),并且由于10是右值,T&&在这里实际上变成了int&&,即一个对int类型的右值引用。这其实并没有用引用折叠。
用下面的代码调用时:
int a = 10;
Test(a);
调用 Test 函数并将a作为参数传递进去。由于传递的是左值, T会被推导为int&,这就变为了int& && 然后根据引用折叠规则最后就变为了int&,即一个对int类型的左值引用。
这样一份代码就可以实现左值引用和右值引用,是不是方便了不少。
实际应用
移动语义
移动语义指的是通过移动构造函数和移动赋值运算符,将资源的所有权从一个对象转移到另一个对象,即新对象直接管理原对象的内存资源,原对象仍然处于有效状态,但不再持有任何资源。它们的主要目的是优化资源管理和提升程序性能。
移动构造函数
可以简单认为移动构造函数的实现是通过下面的方式:
void swap(string& s)
{std::swap(_str, s._str);//首元素地址std::swap(_size, s._size);//字符串长度std::swap(_capacity, s._capacity);//容量
}
// 移动构造
string(string&& rs)
{swap(rs);
}
rs是右值引用但它的属性是左值,所以在swap()里用的是左值引用。
示例:
string Test()
{string str("Happy New Year");//...return str;
}int main()
{string ret = Test();return 0;
}
不需要关心上面的函数是用来做什么的,这里我就只拿关键的部分。之前要想把str的值传给ret就要先创建一个临时对象,然后把str里的值拷贝构造给临时对象,然后临时对象在拷贝构造给ret。
使用两次拷贝构造这代价可不小,要是使用移动语义的话可就不一样了。移动语义相当于“掠夺”并不进行拷贝,这代价就很小了。
移动赋值运算符
它的简单实现和移动构造函数可以说是一样的。
// 移动赋值
string& operator=(string&& s)
{swap(s);return *this;
}
示例:
string Test()
{string str("Happy New Year");//...return str;
}int main()
{string ret;ret = Test();return 0;
}
之前要想把str的值传给ret就要先创建一个临时对象,然后把str里的值拷贝构造给临时对象,然后临时对象在拷贝赋值给ret。
当有了移动语义后就只是进行简单交换。
上面我所介绍的str值传给ret的过程,是编译器没有进行任何优化。我在这里就不介绍编译器具体怎么优化它们了,大家感兴趣可以自己上网查查。
现在我解答一下为什么使用move()后,原对象通常处于不确定状态。这是因为当move()把对象转换为右值后,会自动调用移动语义而造成的。例如:
int main()
{string s("haha");cout << "s:" << s << endl;string rs = move(s);cout << "s:" << s << endl;return 0;
}
完美转发
完美转发在C++编程中具有重要意义,它提高了代码的复用性、性能和可维护性。先看如下代码:
void Fun(int&& x)
{cout << "右值引用" << endl;
}void Fun(int& x)
{cout << "左值引用" << endl;
}template<class T>
void Test(T&& x)
{Fun(x);
}int main()
{int a = 1;Test(a);Test(1);return 0;
}
这是运行结果:
为什么第二个也是左值引用?我在上面提到过右值引用它自身作为一个变量是左值,所以这里就是左值引用。但是这样会降低运行效率,其解决方案就是用完美转发std::forward函数,它能够保持参数的左、右值属性不变,并将其转发给目标函数。具体使用方法如下:
template<class T>
void Test(T&& x)
{Fun(forward<T>(x));
}
修改后的结果:
完美转发forward本质是⼀个函数模板,他主要还是通过引用折叠的方式实现,上面示例中传递给Func的实参是右值,T被推导为int,没有折叠,forward内部 x 被强转为右值引用返回。当传递给Func的实参是左值,T被推导为int&,引用折叠为左值引用,forward内部 x 被强转为左值引用返回。
注意传递参数包过程中,如果是 Args&&... args 的参数包,要用完美转发参数包,方式如下std::forward<Args>(args)... 。
相关文章:
C++11—右值引用
目录 简介 左值和右值 左值 右值 右值引用 生命周期 引用折叠 实际应用 移动语义 移动构造函数 移动赋值运算符 完美转发 简介 之前我们曾学习过引用叫左值引用,但那是C98的,在C11中新增了一种引用叫右值引用。右值引用主要用于支持移动语…...
Workbench 中的热源仿真
探索使用自定义工具对移动热源进行建模及其在不同行业中的应用。 了解热源动力学 对移动热源进行建模为各种工业过程和应用提供了有价值的见解。激光加热和材料加工使用许多激光束来加热、焊接或切割材料。尽管在某些情况下,热源 (q) 不是通…...
Windows11 不依赖docker搭建 deepseek-R1 1.5B版本(附 Open WebUi搭建方式)
零、前言 过年这几天发现 DeepSeek 非常火,试用了一下发现确实不错。与豆包、kimi、perplexity 这些相比完全不是一个次元的存在,特别是用ta写文章的时候体验非常好。所以试着自己搭一个环境。 一、安装 Ollama和DeepSeek-R1 我的安装方式很简单…...
Error: Expected a mutable image
你的函数用了不支持的图片格式比如我的人脸检测,本来要RGB565我却用JPEG所以报错...
【4Day创客实践入门教程】Day2 探秘微控制器——单片机与MicroPython初步
Day2 探秘微控制器——单片机与MicroPython初步 目录 Day2 探秘微控制器——单片机与MicroPython初步MicroPython语言基础开始基础语法注释与输出变量模块与函数 单片机基础后记 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机…...
代码随想录算法训练营Day51 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
文章目录 101.孤岛的总面积思路与重点 102.沉没孤岛思路与重点 103.水流问题思路与重点 104.建造最大岛屿思路与重点 101.孤岛的总面积 题目链接:101.孤岛的总面积讲解链接:代码随想录状态:直接看题解了。 思路与重点 nextx或者nexty越界了…...
网络基础
协议 协议就是约定 网络协议是协议中的一种 协议分层 协议本身也是软件,在设计上为了更好的模块化,解耦合,也是设计成为层状结构的 两个视角: 小白:同层协议,直接通信 工程师:同层协议&…...
利用Spring Batch简化企业级批处理应用开发
1. 引言 1.1 批处理的重要性 在现代企业系统中,批处理任务用于处理大量数据,如报表生成、数据迁移、日终结算等。这些任务通常不需要实时响应,但需要高效、可靠地完成。批处理可以显著提高系统性能,减少实时系统的负载,并确保数据的完整性和一致性。 1.2 Spring Batch简…...
Python - pyautogui库 模拟鼠标和键盘执行GUI任务
安装库: pip install pyautogui 导入库:import pyautogui 获取屏幕尺寸: s_width, s_height pyautogui.size() 获取鼠标当前位置: x, y pyautogui.position() 移动鼠标到指定位置(可以先使用用上一个函数调试获取当…...
UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备
1 将用到的图标找好,放一起 DataTable里对应好图标 测试一下能正确获取: 2 装备增强属性思路 给FMyItemInfo添加一个枚举变量记录类型(物品,道具,装备,饰品,武器)--> 扩展DataT…...
【PyQt】lambda函数,实现动态传递参数
为什么需要 lambda? 在 PyQt5 中,clicked 信号默认会传递一个布尔值(表示按钮是否被选中)。如果我们希望将按钮的文本内容传递给槽函数,需要通过 lambda 函数显式传递参数。 这样可以实现将按钮内容传递给槽函数&…...
Unity 2D实战小游戏开发跳跳鸟 - 跳跳鸟碰撞障碍物逻辑
在有了之前创建的可移动障碍物之后,就可以开始进行跳跳鸟碰撞到障碍物后死亡的逻辑,死亡后会产生一个对应的效果。 跳跳鸟碰撞逻辑 创建Obstacle Tag 首先跳跳鸟在碰撞到障碍物时,我们需要判定碰撞到的是障碍物,可以给障碍物的Prefab预制体添加一个Tag为Obstacle,添加步…...
LeetCode:121.买卖股票的最佳时机1
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:121.买卖股票的最佳时机1 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票…...
DeepSeek-R1 论文. Reinforcement Learning 通过强化学习激励大型语言模型的推理能力
论文链接: [2501.12948] DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning 实在太长,自行扔到 Model 里,去翻译去提问吧。 工作原理: 主要技术,就是训练出一些专有用途小模型&…...
SQL索引优化_提高系统响应速度的秘诀
1. 引言 1.1 索引的重要性 在数据库管理系统中,索引是提升查询性能的关键工具。合理的索引设计可以显著减少查询时间,提高系统的响应速度,从而改善用户体验。然而,不恰当的索引使用可能会适得其反,增加写操作的开销并导致性能下降。 1.2 文章目标与结构 本文旨在介绍如…...
MoonBit 编译器(留档学习)
MoonBit 编译器 MoonBit 是一个用户友好,构建快,产出质量高的编程语言。 MoonBit | Documentation | Tour | Core This is the source code repository for MoonBit, a programming language that is user-friendly, builds fast, and produces high q…...
基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)
酒店管理小程序目录 目录 基于微信小程序的酒店管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1) 用户信息管理 (2) 酒店管理员管理 (3) 房间信息管理 2、小程序序会员模块的实现 (1)系统首页 ÿ…...
重生之我在异世界学编程之C语言:深入指针篇(上)
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文(1)内置数…...
Unity Shader Graph 2D - 跳动的火焰
在游戏中,火焰是一种常见的特效。通常来讲火焰特效通过粒子系统的方式实现的相对较多,本文将通过Shader Graph的方式来实现一种不同的火焰效果。 那么怎么实现呢 首先创建一个名为Fire的Shader Graph文件,然后创建一个名为M_Fire的材质球。 …...
CoRAG 来自微软与人大的创新RAG框架技术
微软与人大合作开发的CoRAG(Chain-of-Retrieval Augmented Generation)是一种创新的检索增强生成(RAG)框架,旨在通过模拟人类思考方式来提升大语言模型(LLM)在复杂问题上的推理和回答能力。以下是对CoRAG的深度介绍: 1. CoRAG的核心理念 CoRAG的核心思想是通过动态调…...
MySQL的GROUP BY与COUNT()函数的使用问题
在MySQL中,GROUP BY和 COUNT()函数是数据聚合查询中非常重要的工具。正确使用它们可以有效地统计和分析数据。然而,不当的使用可能会导致查询结果不准确或性能低下。本文将详细讨论 GROUP BY和 COUNT()函数的使用方法及常见问题,并提供相应的…...
DS常识问答:人民币升值贬值是什么回事
好的!我用一个简单的比喻来解释,就像用苹果换橘子一样: 1. **汇率是什么?** 假设你有人民币,别人有美元。汇率就是你们交换的“价格”。比如今天1美元能换7块人民币,明天可能变成7.5块或者6.5块&…...
docker直接运行arm下的docker
运行环境是树莓派A 处理器是 arm32v6 安装了docker,运行lamp 编译安装php的时候发现要按天来算,于是用电脑vm下的Ubuntu系统运行arm的docker 然后打包到a直接导入运行就可以了 第一种方法 sudo apt install qemu-user-static 导入直接运行就可以了…...
机器学习--概览
一、机器学习基础概念 1. 定义 机器学习(Machine Learning, ML):通过算法让计算机从数据中自动学习规律,并利用学习到的模型进行预测或决策,而无需显式编程。 2. 与编程的区别 传统编程机器学习输入:规…...
人机交互系统实验三 多通道用户界面
实验目的和要求 1)了解常见的多通道用户界面 2)查找资料,熟悉一种多通道用户界面并写出综述 实验环境 Windows10 实验内容与过程 (一) 实验内容: 要求上网查找资料,熟悉一种多通道用户界面并写出综述,可以是眼动跟踪、手势识别、 三维…...
Python(Pandas)数据分析学习
1.Pandas基本构成 引入Pandas import pandas as pd 1.Series 行 对应Excel中的一行数据,一维数据 定义Series # 第一个参数是具体数据 # 第二个参数的对应的索引下标 # 第三个参数的行名称 data pd.Series([1,2,3,4,5], index[a,b,c,d,e], namedata) print(d…...
JavaScript系列(53)--内存管理与垃圾回收机制详解
JavaScript内存管理与垃圾回收机制详解 🧹 今天,让我们深入探讨JavaScript的内存管理与垃圾回收机制。理解这些机制对于编写高性能、无内存泄漏的JavaScript应用至关重要。 内存管理基础概念 🌟 💡 小知识:JavaScrip…...
每日一题——用两个栈实现队列
用两个栈实现队列 题目描述数据范围示例 代码实现1. 代码思路push 操作:pop 操作: 2. 代码实现3. 代码解析4. 时间复杂度与空间复杂度 总结 题目描述 用两个栈来实现一个队列,使用 n 个元素来完成 n 次在队列尾部插入整数(push)和 n 次在队列…...
DeepSeek与OpenAI:谁是AI领域的更优选择?
在人工智能领域,DeepSeek和OpenAI是两个备受瞩目的玩家。尽管OpenAI凭借其强大的GPT系列模型在全球范围内获得了广泛的认可,但DeepSeek凭借其独特的技术优势和创新理念,正在逐渐成为许多企业和开发者的新选择。本文将对DeepSeek和OpenAI进行详…...
【爬虫】JS逆向解决某药的商品价格加密
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...
deepseek v3 搭建个人知识库
目录 deepseek-r1本地部署,这个比较好,推荐 Chatbox连接ollama服务 知乎教程,需要注册: deepseek-r1本地部署,这个比较好,推荐 公司数据不泄露,DeepSeek R1本地化部署web端访问个人知识库搭建…...
ETCD集群证书生成
安装cfssl工具配置CA证书请求文件创建CA证书创建CA证书策略配置etcd证书请求文件生成etcd证书 继续上一篇文章《负载均衡器高可用部署》下面介绍一下etcd证书生成配置。其中涉及到的ip地址和证书基本信息请替换成你自己的信息。 安装cfssl工具 下载cfssl安装包 https://github…...
【软件测试项目实战】淘宝网订单管理功能
一、测试功能模块分析 选择淘宝网订单管理功能进行测试,核心子功能包含: 订单创建(商品结算、地址选择)订单状态变更(待付款、已付款、已发货、已收货、退款中)订单修改(地址修改、商品数量修…...
扩散模型(一)
在生成领域,迄今为止有几个主流的模型,分别是 GAN, VAE,Flow 以及 Diffusion 模型。 GAN:GAN 的学习机制是对抗性学习,通过生成器和判别器的对抗博弈来进行学习,这种竞争机制促使生成器不断提升生成能力&a…...
EF Core与ASP.NET Core的集成
目录 分层项目中EF Core的用法 数据库的配置 数据库迁移 步骤汇总 注意: 批量注册上下文 分层项目中EF Core的用法 创建一个.NET类库项目BooksEFCore,放实体等类。NuGet:Microsoft.EntityFrameworkCore.RelationalBooksEFCore中增加实…...
深入解析“legit”的地道用法——从俚语到正式表达:Sam Altman用来形容DeepSeek: legit invigorating(真的令人振奋)
深入解析“legit”的地道用法——从俚语到正式表达 一、引言 在社交媒体、科技圈甚至日常对话中,我们经常会看到或听到“legit”这个词。比如最近 Sam Altman 在 X(原 Twitter)上发的一条帖子中写道: we will obviously deliver …...
玩转ChatGPT:DeepSeek测评(科研思路梳理)
一、写在前面 DeepSeek-R1出圈了,把OpenAI的o3-mini模型都提前逼上线了(还免费使用)。 都号称擅长深度推理,那么对于科研牛马的帮助有多大呢? 我连夜试一试。 二、科研思路梳理 有时候我们牛马们做了一堆结果以后&…...
实验9 JSP访问数据库(二)
实验9 JSP访问数据库(二) 目的: 1、熟悉JDBC的数据库访问模式。 2、掌握预处理语句的使用 实验要求: 1、使用Tomcat作为Web服务器 2、通过JDBC访问数据库,实现增删改查功能的实现 3、要求提交实验报告,将代…...
CMake项目编译与开源项目目录结构
Cmake 使用简单方便,可以跨平台构建项目编译环境,尤其比直接写makefile简单,可以通过简单的Cmake生成负责的Makefile文件。 如果没有使用cmake进行编译,需要如下命令:(以muduo库echo服务器为例)…...
PyCharm中使用Ollama安装和应用Deepseek R1模型:完整指南
引言 人工智能和大型语言模型正在改变我们与技术交互的方式。Deepseek R1是一个强大的AI模型,而Ollama则是一个让我们能够轻松在本地运行这些模型的工具。本文将指导您如何使用Ollama安装Deepseek R1模型,并在PyCharm中创建一个简单的聊天应用。 © ivwdcwso (ID: u0121…...
编程AI深度实战:大模型知识一文打尽
系列文章: 编程AI深度实战:私有模型deep seek r1,必会ollama-CSDN博客 编程AI深度实战:自己的AI,必会LangChain-CSDN博客 编程AI深度实战:给vim装上AI-CSDN博客 编程AI深度实战:火的编程AI&…...
012-51单片机CLD1602显示万年历+闹钟+农历+整点报时
1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台,可以根据需要自行焊接模块,这是用立创EDA画的一个双层PCB板,所以模块都是插针式,不是表贴的。电路原理图在文末的链接里,PCB图暂时不选择开源。 B站上传的…...
基于springboot+vue的哈利波特书影音互动科普网站
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
MySQL5.5升级到MySQL5.7
【卸载原来的MySQL】 cmd打开命令提示符窗口(管理员身份)net stop mysql(先停止MySQL服务) 3.卸载 切换到原来5.5版本的bin目录,输入mysqld remove卸载服务 测试mysql -V查看Mysql版本还是5.5 查看了环境变量里的…...
列表标签(无序列表、有序列表)
无序列表 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><…...
【数据结构】_链表经典算法OJ:分割链表(力扣—中等)
目录 1. 题目描述及链接 2. 解题思路 2.1 思路1 2.2 思路2 2.3 思路3(本题采取该解法) 3. 题解程序 1. 题目描述及链接 题目链接:面试题 02.04. 分割链表 - 力扣(LeetCode) 题目描述: 给你一个链表…...
深入核心:一步步手撕Tomcat搭建自己的Web服务器
介绍: servlet:处理 http 请求 tomcat:服务器 Servlet servlet 接口: 定义 Servlet 声明周期初始化:init服务:service销毁:destory 继承链: Tomcat Tomcat 和 servlet 原理&#x…...
ASP.NET Core与配置系统的集成
目录 配置系统 默认添加的配置提供者 加载命令行中的配置。 运行环境 读取方法 User Secrets 注意事项 Zack.AnyDBConfigProvider 案例 配置系统 默认添加的配置提供者 加载现有的IConfiguration。加载项目根目录下的appsettings.json。加载项目根目录下的appsettin…...
在 Ubuntu 上安装 Node.js 23.x
在 Ubuntu 上安装 Node.js 23.x 前提条件安装步骤1. 下载设置脚本2. 运行设置脚本3. 安装 Node.js4. 验证安装 参考链接总结 在现代 web 开发中,Node.js 是一个不可或缺的工具。它提供了一个强大的 JavaScript 运行时环境,使得开发人员可以在服务器端使用…...
《 C++ 点滴漫谈: 二十五 》空指针,隐秘而危险的杀手:程序崩溃的真凶就在你眼前!
摘要 本博客全面解析了 C 中指针与空值的相关知识,从基础概念到现代 C 的改进展开,涵盖了空指针的定义、表示方式、使用场景以及常见注意事项。同时,深入探讨了 nullptr 的引入及智能指针在提升代码安全性和简化内存管理方面的优势。通过实际…...