【C++】踏上C++学习之旅(五):auto、范围for以及nullptr的精彩时刻(C++11)

文章目录

  • 前言
  • 1. auto关键字(C++11)
    • 1.1 为什么要有auto关键字
    • 1.2 auto关键字的使用方式
    • 1.3 auto的使用细则
    • 1.4 auto不能推导的场景
  • 2. 基于范围的for循环(C++11)
    • 2.1 范围for的语法
    • 2.2 范围for的使用条件
  • 3. 指针空值nullptr(C++11)
    • 3.1 为什么会有nullptr这个关键字?

图片

前言

本文我了解一下C++11新特性的auto、范围for以及nullptr给我们的编程带来了什么样的好处,以及我们在特定的场景该如何使用它们。

温馨提示:本文所讲到的C++11(2011年)和C++98(1998年)均为C++编译器的版本。

OK,让我们一起探索这些auto、范围for以及nullptr背后的秘密。

哈哈哈


1. auto关键字(C++11)

这里需要说明的一点是,在C++98就已经有auto这个关键字了。不过在C++98的做法中,它将auto关键字视作一个存储类型的指示符。换句话说,只要是在C++98中使用auto关键字定义的变量就是一个具有自动存储器功能的局部变量 – 待补充

1.1 为什么要有auto关键字

这就要往类型别名的方向去思考这个问题。

想一个现象,随着我们越学到后面,代码就会变得愈加复杂,伴随的是声明类型的长度也会增加,这个就会导致两个问题:

  1. 类型难以拼写;
  2. 类型含义不明确导致出错。

这么说可能有点干巴,下面我来展示一段代码(这个是大家以后学习C++要用到的):

#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;int main()
{std::map<std::string, std::string> m{ {"apple","苹果"},{"orange","橙子"},{"pear","梨"} };std::map<std::string, std::string>::iterator it = m.begin();while (it != m.end()){//...}return 0;
}

上面的std::map<std::string, std::string>std::map<std::string, std::string>::iterator,这两个类型够长吧,即使你能记得住,如果有很多地方都要定义的话,我估计你的键盘可能会敲冒烟。

那有的人就会这么想,那我可以用typedef来给这些长的类型起一个别名,比如下面这样:

#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;
typedef std::map<std::string, std::string>  Map;int main()
{Map m{ {"apple","苹果"},{"orange","橙子"},{"pear","梨"} };Map::iterator it = m.begin();while (it != m.end()){//...}return 0;
}

这个方法确实是可以的,但是你能确保在庞大的代码量面前,你能十分的明确Map这个类型所代表的具体含义吗?本人觉得这是一件很难的事,另外用typedef关键字,还有个重要的细节:

#include<iostream>
using namespace std;typedef int* int_ptr;
int main()
{int num1 = 66,num2 = 88;//写法1:int_ptr a = &num1 , b = &num2;//写法2:int_ptr a = &num1 , *b = &num2;//以上两种写法那个是正确的?
}

答案:写法一是正确的。

#include<iostream>
using namespace std;int main()
{int num1 = 66,num2 = 88;//写法1:int* a = &num1 , b = &num2;//写法2:int* a = &num1 , *b = &num2;//以上两种写法那个是正确的?
}

答案:写法二是正确的。

如果你上面两道题目做对了一道的话,那我想auto关键字就很适合你使用了!

1.2 auto关键字的使用方式

🍉auto 变量名 = 值;
🍇编译器在编译的过程看到auto就会根据赋值符号右边的表达式推导出出变量名的类型!

#include<iostream>
using namespace std;int main()
{auto a = 's';auto b = 66;auto c = 520.13f;auto d = 0.1314;//auto也可以推导出表达式的值的数据类型auto tmp = b + d;//我们可以用typdeid(变量名).name()cout << typeid(a).name() << endl;cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;cout << typeid(tmp).name() << endl;return 0;
}

测试结果

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

1.3 auto的使用细则

  1. auto与指针和引用结合起来使用
    用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。
	//auto*和auto用来代表指针类型都是一样的,但是如果我们要用引用的话,就必须在auto后面加上&。int a = 10;int b = 66;int c = 88;auto* pa = &a;auto pb = &b;auto& ic = c;cout << typeid(pa).name() << endl;cout << typeid(pb).name() << endl;cout << typeid(ic).name() << endl;return 0;

结果
2. 在同一行定义多个变量
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

void TestAuto()
{auto a = 10, b = 20;auto c = 3, d = 4.0; //该行代码会编译失败,因为c和d的初始表达式类型不同
}

1.4 auto不能推导的场景

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

好了,到这里auto关键字的用法也了解的差不多了。那么接下来我们再来看看C++的一个"语法糖"——“范围for”!
hahah


2. 基于范围的for循环(C++11)

2.1 范围for的语法

我们在C++98中如果要遍历一个数组,是这样做的:

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

==对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。==因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

void TestFor()
{int array[] = { 1, 2, 3, 4, 5 };for(auto& e : array)e *= 2;for(auto e : array)cout << e << " ";return 0;
}

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

2.2 范围for的使用条件

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

注意:以下代码就有问题,因为for的范围不确定

void TestFor(int array[])
{for(auto& e : array)cout<< e <<endl;
}
  1. 迭代的对象要实现++和==的操作。(关于迭代器这个问题,以后会讲,现在提一下,没办法讲清楚,现在大家了解一下就可以了)

范围for比较简单,只要求会用就可以了。那接下来再来讲讲另一个关键字"nullptr"!


3. 指针空值nullptr(C++11)

3.1 为什么会有nullptr这个关键字?

有的读者可能会诧异,不是说C++兼容C语言吗?那我们就直接用C语言的NULL作为来表示指针空值就行了啊,为什么C++还要单独再弄一个nullptr关键字出来呢?

我们可以查看C++下的NULL:
在main函数中敲一个NULL,之后点击鼠标右键,然后点击"转到定义"。
步骤一
NULL定义的地方:
大
可以看到的是NULL在cpp文件中是字面常量0

如果我们要是在C++中用NULL,可能会遇到一些麻烦,比如下面的这段代码:

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

图

程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。

在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void *)0。

注意:

  1. 🍉在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 🍉 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 🍉为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

好了,到这里,你感受到了auto、范围for和nullptr的魅力了吗?

如果觉得本文写的不错的话,麻烦给偶点个赞吧!!!

hahaha

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

科研绘图系列:R语言组合多个不同图形(violin density barplot heatmap)

文章目录 介绍加载R包数据下载函数图1: Boxplots导入数据数据预处理画图图2: Violin导入数据数据预处理画图图3: Density plots per habitat数据预处理画图图4: Density plots per depth数据预处理画图图5: bar plot准备颜色导入数据数据预处理数据预处理画图图6: Mantel Heat…

系统聚类的分类数确定——聚合系数法

breast_cancer数据集分析——乳腺癌诊断 #读取乳腺癌数据 import pandas as pd import numpy as np from sklearn.datasets import load_breast_cancer data load_breast_cancer() X data.data y data.target.. _breast_cancer_dataset:Breast cancer wisconsin (diagnosti…

jsp+sevlet+mysql实现用户登陆和增删改查功能

jspsevletmysql实现用户登陆和增删改查功能 一、系统介绍二、功能展示1.用户登陆2.用户列表3.查询用户信息4.添加用户信息5.修改用户信息6.删除用户信息 四、其它1.其他系统实现 一、系统介绍 系统主要功能&#xff1a; 用户登陆、添加用户、查询用户、修改用户、删除用户 二…

一文了解Java序列化

Java 序列化&#xff08;Serialization&#xff09;是将对象的状态转换为字节流&#xff0c;以便将对象的状态保存到文件中或通过网络传输的过程。反序列化&#xff08;Deserialization&#xff09;则是将字节流恢复为原始对象。Java 序列化主要通过 Serializable 接口实现。 为…

斗破QT编程入门系列之前言:认识Qt:获取与安装(四星斗师)

本系列是在学习完C之后&#xff0c;然后通过Qt构建界面来&#xff0c;赋予枯燥的代码新的样貌&#xff0c;这样我们才能开发出更人性化的程序&#xff0c;同时会进一步提高初学者对编程的兴趣&#xff0c;大家加油&#xff0c;斗破Qt来了。 斗破Qt目录&#xff1a; 斗破Qt编程…

Spring Boot - 扩展点 EnvironmentPostProcessor源码分析及真实案例

文章目录 概述EnvironmentPostProcessor 作用EnvironmentPostProcessor 实现和注册创建类并实现接口注册到 Spring Boot常见应用场景 源码分析1. EnvironmentPostProcessor 接口定义2. 扩展点加载流程3. 加载 EnvironmentPostProcessor 实现类4. EnvironmentPostProcessor 执行…

封装的数字滚动组件的实现代码

效果&#xff1a; 学习啦&#xff1a; Vue 是一个渐进式框架&#xff0c;鼓励通过组件化来构建应用&#xff0c;其组件化优势&#xff1a; 代码复用&#xff1a;不同的视图和功能被封装成独立的组件&#xff0c;便于复用。易于维护&#xff1a;每个组件职责单一、耦合度低&…

Unity跨平台基本原理

目录 前言 ​编辑 Mono Unity和Mono的关系 Unity跨平台必备概念 Mono利用 Mono主要构成部分 基于Mono跨平台的优缺点 IL2CPP Mono和IL2CPP的区别 Mono IL2CPP Mono和IL2CPP的使用建议 安装IL2CPP IL2CPP打包存在的问题 类型裁剪 泛型问题 前言 Unity跨平台的基…

计算机网络(3)

UDP是面向无连接的通信协议&#xff0c;UDP数据包括目的端口号和源端口号信息&#xff0c;由于 不需要连接&#xff0c;所以可以实现广播发送&#xff1b; 传输控制层 UDP协议&#xff08;用户数据报协议&#xff09; UDP通信时不需要接收方确认&#xff0c;属于不可靠的传输&a…

2024年11月8日上海帆软用户大会

2024年11月8日上海帆软用户大会 2024年11月8日&#xff0c;上海成功举办了帆软用户大会&#xff0c;主题为“数字聚力&#xff0c;绽放新机”。大会汇聚了众多行业专家和企业代表&#xff0c;共同探讨数字化转型和商业智能领域的最新趋势和实践。 大会亮点&#xff1a; 专家…

PySimpleGUI和Pymysql

PySimpleGUI 库 PySimpleGUI 是一个用于简化 GUI 编程的 Python 包&#xff0c;它封装了多种底层 GUI 框架&#xff08;如 tkinter、Qt、WxPython 等&#xff09;&#xff0c;提供了简单易用的 API。PySimpleGUI 包含了大量的控件&#xff08;也称为小部件或组件&#xff09;&…

Qt Event事件系统小探1

目录 Qt Event System From qt.doc 如何传递事件 事件类型 事件处理程序 事件过滤器 发送事件 事件的产生和派发 处理我们的事件 来一段好玩的代码 扩展&#xff1a;QWidget如何处理我们的事件&#xff1f; 扩展2&#xff1a;实现一个变色的Label Qt Event System Fr…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于凸多面体仿射变换的用户侧灵活性资源多元聚合方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

vue3组合式API下封装hooks使用生命周期,在await之后调用hooks会有警告

起因&#xff1a;想封装一个hooks实现echarts图表随屏幕大小resize并且组件销毁时移除监听。结果在组件里面调用这个hooks&#xff0c;有个告警提示 [Vue warn]: onBeforeUnmount is called when there is no active component instance to be associated with. Lifecycle inje…

使用Python实现图像的手绘风格效果

使用Python实现图像的手绘风格效果 一、引言二、代码详细解释与示例三、完整框架流程四、运行五、结论附&#xff1a;完整代码 一、引言 在数字图像处理领域&#xff0c;模拟手绘风格是一项有趣且具有挑战性的任务。手绘风格图像通常具有独特的纹理和深浅变化&#xff0c;给人…

window中借助nginx配置vite+vue项目的反向代理步骤

在官网下载好nginx的安装包后&#xff0c;解压后 CMD打开 start nginx 是启动命令 nginx -s stop 停止服务 nginx -s reload 如果重写了nginx.conf文件&#xff0c;要执行这条命令 正常情况下 成功启动和成功停止服务长这样 错误情况&解决 如果nginx -s stop失败 ngi…

花指令例子

如图所示&#xff1a; 指令EB FF的汇编代码为jmp -1&#xff0c;CPU执行到地址处0x6c80c0的指令EB FF时(jmp -1)&#xff0c;EIP为6c80c2, 执行后&#xff0c;EIP为0x6c80c1。但是反汇编器无法自动识别该指令。

关于我的编程语言——C/C++——第八篇

&#xff08;叠甲&#xff1a;如有侵权请联系&#xff0c;内容都是自己学习的总结&#xff0c;一定不全面&#xff0c;仅当互相交流&#xff08;轻点骂&#xff09;我也只是站在巨人肩膀上的一个小卡拉米&#xff0c;已老实&#xff0c;求放过&#xff09; 什么是C C语言是结…

博客园美化

1、主题介绍 使用的 SimpleMemory 这款主题 github官网 2、设置主题并申请 js 代码权限 3、主题设置 博客侧边栏公告 <script type"text/javascript">window.cnblogsConfig {info: {blogIcon: https://ts1.cn.mm.bing.net/th/id/R-C.85775e482741cb7ab7f…

SpringBoot基础系列学习(二):配置详解

文章目录 一丶依赖二丶配置文件三丶获取配置文件中的信息1.PropertySource("classpath:application2.properties")2. ConfigurationProperties(prefix "baicaizhi1")3. Value4. 使用EnviromentgBean获取5. 使用ResourceBundle获取 一丶依赖 <dependen…