【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《C++干货基地》《粉丝福利》

⛺️生活的理想,就是为了理想的生活!

引入

  哈喽各位铁汁们好啊,我是博主鸽芷咕《C++干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的城市有没有这种实惠又全面的零食基地呢?C++ 本身作为一门篇底层的一种语言,世面的免费课程大多都没有教明白。所以本篇专栏的内容全是干货让大家从底层了解C++,把更多的知识由抽象到简单通俗易懂。

⛳️ 推荐

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

文章目录

  • 引入
  • ⛳️ 推荐
  • 一、内联函数
    • 1.1 内联函数的概念
    • 1.2 内联函数的特性
      • 内联函数适合每个函数都用吗?
      • 内联函数需要声明和定义分离吗?
  • 二、auto关键字
    • 2.1 auto 的使用场景
    • 2.2 auto 不能推导的场景
  • 三、基于范围for循环
    • 3.1 范围for的语法
    • 3.2 范围for 的注意事项
  • 四、指针空值 nullptr
    • 4.1 C++98中的指针空值
    • 4.2 nullptr的由来
  • 📝文章结语:

一、内联函数

1.1 内联函数的概念

以往我们在C语言中实现比较简单的函数来说都是用宏来实现的,比如说实现一个加法,但是用宏实现的小型函数有很多缺点:

  • 第一点就是宏经常容易写错,末尾的引号问题和运算符优先级问题等等
  • 第二点就是宏他并没有类型安全检查就算是一个加法也有可能有人给你传俩个字符
  • 第三点就是宏不方便调试,导致代码可读性差

所以在C++中就采用了内联函数和枚举来解决宏的使用的问题

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。

1.2 内联函数的特性

内联函数是以inline修饰的函数,在调用其该函数的时候会直接在调用处展开并不会开辟函数的栈帧空间所以非常适用在一下短小函数上面:

下面就给大家来看一下使用内联函数的效果:

🍸 代码一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

int Add(int x, int y)
{
	int ret = x + y;
	return ret;
}

int main()
{
	int ret = Add(1,2);
	return 0;
}

在这里插入图片描述

🍸 代码二:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

inline int Add(int x, int y)
{
	int ret = x + y;
	return ret;
}

int main()
{
	int ret = Add(1,2);
	return 0;
}

在这里插入图片描述
这里我们就可以看到只要函数我们加了 inline 关键字在调用的时候就直接展开不会开辟新的栈帧空间然后去 call 调用它。

内联函数适合每个函数都用吗?

内联函数看起来不用开辟函数的栈帧空间大大结束了效率但是每个短小的函数都适合使用内联函数吗?

  • 其实函数在调用次数过多的情况下就不适合使用内联函数,这样就会导致代码膨胀到处都是重复的代码,从而使得可执行程序变大;
  • 还有在函数的递归时也不能使用内联函数,函数栈帧是可以复用的,但内联函数一旦使用也会导致代码膨胀

🔥 注: inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不
是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为
《C++prime》第五版关于inline的建议:

在这里插入图片描述

内联函数需要声明和定义分离吗?

inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
了,链接就会找不到。

在这里插入图片描述

二、auto关键字

auto 关键字听听名字就非常简单,是C++11的时候,标准委员会赋予了auto全新的含义即可以自动推导变量类型使用起来也十分简单:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

int main()
{
	int a = 10;
	auto p1 = a;
	auto* p2 = &a;
	auto& p3 = a;

	return 0;
}

这里auto后面加的 * 号就代表指针,&和以前一样是引用是我们指定自动类型。

🔥 注:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。
因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

2.1 auto 的使用场景

auto 关键的意义其实并不是像我们前面那样去使用,是针对特别复杂的类型配合使用的比如:

🍸 场景一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

int fun(int x, int y)
{
	int ret = x + y;
	return ret;
}
int main()
{
	int(*fp1)(int, int) = fun;
	auto fp2 = fun;

	return 0;
}

🍸 场景一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<map>
#include<string>
using namespace std;

int main()
{
	std::map<std::string, std::string> dict;
	std::map<std::string, std::string>::iterator it = dict.begin();
	auto it = dict.begin();

	return 0;
}

2.2 auto 不能推导的场景

  • auto不能作为函数的参数
// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}
  • auto不能直接用来声明数组
void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {456};
}

三、基于范围for循环

在以前只要遍历数组我们就可能想到,使用for循环来遍历数组比如这样:

void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
     array[i] *= 2;
for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)
     cout << *p << endl;
}

但是使用这种方法遍历数组太麻烦了,而且还不好写比较繁琐所以在C++11 中新增加了范围 for 的概念

3.1 范围for的语法

for循环后的括号由冒号“ :”分为两部分:

  • 第一部分是范围内用于迭代的变量
  • 第二部分则表示被迭代的范围。
void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for(auto& e : array)
    	 e *= 2;
	for(auto e : array)
    	 cout << e << " ";
}

在这里就巧妙的运用了我们上面讲的 auto 关键字来自动识别数组元素的类型:

  • e 在这里是数组元素的临时拷贝所以我们如果想要改变数组元素
  • 就得指定自动类型为引用,去用于改变数组元素

3.2 范围for 的注意事项

🔥 for循环迭代的范围必须是确定的

  • 对于数组而言,就是数组中第一个元素和最后一个元素的范围;
  • 对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

例如以下代码就是错误的:

  • 这里我们并不明确因为for的范围不确定
void TestFor(int array[])
{
    for(auto& e : array)
        cout<< e <<endl;
}

四、指针空值 nullptr

4.1 C++98中的指针空值

一般我们定义变量好的习惯是每一个变量都初始化值但是 C++98 中 祖师爷在定义 NULL 指针空值的时候是这样定义的:

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

这就导致了一个问题大家看一下下面这个代码结果你们猜是什么呢?

void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}
int main()
{
	f(0);
	f(NULL);
	f((int*)NULL);
	return 0;
}

在这里插入图片描述

诶这里使用指针 NULL 定义空值的时候就出现问题了,所以在C++11中新增了一个关键字来填这个缺陷

4.2 nullptr的由来

nullptr 的由来就是因为祖师爷在一开始定义 NULL是使用宏定义这就导致

  • NULL 被替换成 0 了,而不是((void *)0);
  • 所以新增了一个关键字 nullptr == ((void *)0);

注意:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。

  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。

  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

📝文章结语:

☁️ 看到这里了还不给博主扣个:
⛳️ 点赞🍹收藏 ⭐️ 关注
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/425432.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Dockerfile构建过程详解

Dockerfile介绍 docker是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 1、编写一个dockerfile文件 2、docker build构建成为一个镜像 3、docker run 运行镜像 …

如何在Window系统部署VisualSVN服务并结合cpolar实现无公网ip远程访问

文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统…

mongoDB 优化(1)索引

1、创建复合索引&#xff08;多字段&#xff09; db.collection_test1.createIndex({deletedVersion: 1,param: 1,qrYearMonth: 1},{name: "deletedVersion_1_param_1_qrYearMonth_1",background: true} ); 2、新增索引前&#xff1a; 执行查询&#xff1a; mb.r…

[业务系统]人物坐骑系统介绍I

1.问题描述 旧版本的坐骑系统依赖于人物装备了【法宝】&#xff08;一种装备类型&#xff09;&#xff0c;装备了法宝的人物变拥有了【幻化】坐骑的能力&#xff0c;即在人物装备栏中的【外观】中会有已经幻化和未幻化&#xff08;解锁&#xff09;的坐骑。如果玩家至少幻化一…

【笔试强训错题选择题】Day5.习题(错题)解析

文章目录 前言 错题题目 错题解析 总结 前言 错题题目 1. ​ ​ 2. 3. ​ 4. ​ 5. ​ 错题解析 1. 移位运算符的使用 2. 3. 4. 5. 总结

股票技术指标(包含贪婪指数)

股票技术指标是用于分析股票价格和成交量数据&#xff0c;以便预测未来市场走势的工具。技术分析师使用这些指标来识别市场趋势、价格模式、交易信号和投资机会。技术指标通常基于数学公式&#xff0c;并通常在股票价格图表上以图形形式表示。 技术指标主要分为以下几类&#x…

过于老旧的pytorch_ssim包 请从github下载源码

有些冷门算法真的不要随便pip&#xff0c;有可能下载到史前版本…最好还是找源代码 汗 今天要用到SSIM损失函数&#xff0c;从网上简单看了一下原理就想测试一下&#xff0c;偷了一下懒就直接在命令行输入pip install pytorch_ssim了&#xff0c;结果报了一堆错误&#xff08;汗…

冒泡排序(C语言详解)

原理&#xff1a;从左到右一次比较&#xff0c;如果左侧数字比右侧数字大&#xff08;小&#xff09;&#xff0c;则两数交换&#xff0c;否则比较下一 组数字&#xff0c;每一次大循环比较可以将乱序的最右侧数字改为最大&#xff08;最小&#xff09;&#xff0c…

在springboot项目中调用通义千问api多轮对话并实现流式输出

官网文档 阿里灵积提供了详细的官方文档 如何实现多轮对话 官方文档中提到只需要把每轮对话中返回结果添加到消息管理器中&#xff0c;就可以实现多轮对话。本质上就是将历史对话再次发送给接口。 如何实现流式输出 官方文档中提出使用streamCall()方法就可以实现流式输出&…

本届挑战赛亚军方案:基于大模型和多AGENT协同的运维

“轻舟已过万重山团队”荣获本届挑战赛亚军&#xff0c;该团队来自华为集团IT-UniAI 产品和openEuler系统智能团队。 方案介绍 自ChatGPT问世以来&#xff0c;AI迎来了奇点iPhone时刻&#xff0c;这一年来大模型深入影响企业办公&#xff0c;金融&#xff0c;广告&#xff0c;…

上位机图像处理和嵌入式模块部署(上、下位机通信的三个注意点)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 如果最终部署在客户现场的是一个嵌入式设备&#xff0c;那么上位机在做好了算法编辑和算法部署之后&#xff0c;很重要的一步就是处理上位机和下位…

Mybatis 主从表有名字相同,只能查询出一条数据

Mybatis 主从表有名字相同&#xff0c;只能查询出一条数据 重新命名后&#xff0c;可以正常查询

【HarmonyOS】鸿蒙开发之Stage模型-UIAbility的启动模式——第4.4章

UIAbi lity的启动模式简介 一共有四种:singleton,standard,specified,multion。在项目目录的:src/main/module.json5。默认开启模式为singleton(单例模式)。如下图 singleton&#xff08;单实例模式&#xff09;启动模式 每个UIAbility只存在唯一实例。任务列表中只会存在一…

多个地区地图可视化

1. 配置Json文件 1.1 获得每个省份的json数据 打开 阿里云数据可视化平台 主页。 在搜索框中输入所需省份。 将json文件下载到本地。 1.2 将各省份的json数据进行融合 打开 geojson.io 主页 点击 open&#xff0c;上传刚刚下载的 json 文件&#xff0c;对多个省份不断…

SpringCloud负载均衡源码解析 | 带你从表层一步步剖析Ribbon组件如何实现负载均衡功能

目录 1、负载均衡原理 2、源码分析 2.1、LoadBalanced 2.2、LoadBalancerClient 2.3、RibbonAutoConfiguration 2.4、LoadBalancerAutoConfiguration 2.5、LoadBalancerIntercepor⭐ 2.6、再回LoadBalancerClient 2.7、RibbonLoadBalancerClient 2.7.1、DynamicServe…

JavaScript进阶-高阶技巧

文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变this 性能优化防抖节流 高阶技巧 深浅拷贝 只针对引用类型 浅拷贝 拷贝对象后&#xff0c;里面的属性值是简单数据类型直接拷贝值&#xff0c;如果属性值是引用数…

matlab 写入格式化文本文件

目录 一、save函数 二、fprintf函数 matlab 写入文本文件可以使用save和fprintf函数 save输出结果: fprintf输出结果: 1.23, 2.34, 3.45 4.56, 5.67, 6.78 7.89, 8.90, 9.01 可以看出fprintf输出结果更加人性化,符合要求,下面分别介绍。 一、save函数 …

【前端寻宝之路】学习如何使用HTML实现简历展示和填写

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iJ3Ou0qMGFVaqVQq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

哈希表是什么?

一、哈希表是什么&#xff1f; 哈希表&#xff0c;也称为散列表&#xff0c;是一种根据关键码值&#xff08;Key value&#xff09;直接进行访问的数据结构。它通过把关键码值映射到表中一个位置来访问记录&#xff0c;从而加快查找速度。这个映射函数叫做散列函数&#xff08…

【字符串相加】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 字符串相加 方法一&#xff1a; 方法二&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升起的太阳&#xff0c;一种是正在努力学习编程的…
最新文章