Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++】踏上C++学习之旅(五):auto、范围for以及nullptr的精彩时刻(C++11)

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

作者头像
埋头编程
发布于 2024-11-15 00:42:38
发布于 2024-11-15 00:42:38
32602
代码可运行
举报
文章被收录于专栏:C/C++C/C++
运行总次数:2
代码可运行
图片
图片

前言

本文我了解一下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++要用到的):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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来给这些长的类型起一个别名,比如下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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关键字,还有个重要的细节:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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;
	//以上两种写法那个是正确的?
}

答案:写法一是正确的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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就会根据赋值符号右边的表达式推导出出变量名的类型!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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声明引用类型时则必须加&。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	//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. 在同一行定义多个变量 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void TestAuto()
{
	auto a = 10, b = 20;
	auto c = 3, d = 4.0; //该行代码会编译失败,因为c和d的初始表达式类型不同
}

1.4 auto不能推导的场景

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

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

hahah
hahah

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

2.1 范围for的语法

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的范围不确定

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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,可能会遇到一些麻烦,比如下面的这段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的魅力了吗?

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++入门知识(二)
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
海盗船长
2020/08/27
5860
【C++11】入门基础
C++11是C++编程语言的一个重要版本,它于2011年发布。相比于C++98/03,C++11给C++带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。C++11能更好地用于系统开发和库开发、语法更加泛化和简单化,更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习。
大耳朵土土垚
2024/08/29
2240
【C++11】入门基础
C++心决之内联函数+auto关键字+指针空值
以 inline 修饰 的函数叫做内联函数, 编译时 C++ 编译器会在 调用内联函数的地方展开 ,没有函数调
一枕眠秋雨
2024/04/04
1740
C++心决之内联函数+auto关键字+指针空值
解析C++内联函数与auto关键字
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
Yui_
2024/10/16
1290
解析C++内联函数与auto关键字
【C++入门】auto关键字
在C语言中auto修饰的变量,是具有自动存储器的局部变量,但因为局部变量默认类别默认是auto修饰导致一直没有人去使用它。
薄荷冰
2024/01/22
1890
【C++入门】auto关键字
C++入门(2)
大家先回顾一下C语言里面的宏,如果写一个Add的宏,最后一种才是正确的,这就证明了宏是不好控制的,因为运算符的优先级的原因等等,所以宏就有一些缺点:
用户10923087
2024/01/23
1720
【C++11】auto && decltype && nullptr
​ 在 C++98 中 auto 是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以 auto 就没什么价值了。
利刃大大
2025/03/14
940
【C++修炼之路】C++入门 探究根源的奥秘 下
新年快乐!祝大家在新的一年里事事顺心、万事如意。书接上回,我们继续讲解C++的基本语法
f狐o狸x
2025/01/12
980
【C++修炼之路】C++入门 探究根源的奥秘 下
【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值
内联函数是以inline修饰的函数,在调用其该函数的时候会直接在调用处展开并不会开辟函数的栈帧空间所以非常适用在一下短小函数上面:
鸽芷咕
2024/05/25
1470
【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值
【C++ 初阶】内联 auto&范围for循环&指针空值
如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的 调用。 查看方式: 1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add 2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不 会对代码进行优化,以下给出vs2013的设置方式)
IsLand1314
2024/10/15
1990
【C++ 初阶】内联 auto&范围for循环&指针空值
C++命运石之门代码抉择:C++入门(下)
基于当前 C++11 的广泛应用,这里优先介绍几个 C++ 内容,方便后续讲解类和对象及 STL 库🙌
DARLING Zero two
2025/06/02
570
C++11特性:auto关键字
本文的内容已经不新鲜了。关于auto,翻来覆去被人知道的都是这些东西,本文并没有提出新颖的auto用法。 本人原是痛恨博客一篇篇都是copy而来缺乏新意的探索,当然,本文不是copy而来,但发布这样一篇大家皆知的文章心里甚是惶恐。 本文对auto的内容加以整理,权当是自己的复习笔记了。
Tencent JCoder
2022/05/06
4340
C++从入门到精通——auto的使用
C++的auto关键字用于自动推导变量的类型,让编译器根据变量的初始化表达式来确定其类型。使用auto可以简化代码,并且可以在某些情况下提高代码的可读性和灵活性。
鲜于言悠
2024/04/02
8210
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
引用不是新定义一个变量,而是给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
枫叶丹
2024/06/04
2250
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++入门】—— C++入门 (下)_内联函数
前言:在了解完前面的C++基础内容后,马上我们就要真正不如C++的学习了,但在之前让我们最后了解最后一点点C++入门知识!来迟的520特别篇!
Eternity._
2024/06/14
1470
【C++入门】—— C++入门 (下)_内联函数
[C++]C++基础知识概述
  C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适,为了解决软件危机,20世纪80年代,计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
IT编程爱好者
2023/04/12
1.1K0
[C++]C++基础知识概述
【C++】C++基础语法
     当我们协同完成一个项目时,你定义的变量会不会与其他人定义的变量名冲突???
The sky
2023/04/12
1.5K0
【C++】C++基础语法
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
引用不是用于新定义变量,而是对已存在变量取别名。对于引用变量来说,编译器不会为其开辟空间(底层实际开辟),它与被引用变量共同占用同块内存空间
是店小二呀
2024/08/05
1980
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
【C++】内联函数&auto&范围for循环&nullptr
在C语言中,我们为了减少栈帧的开销,我们可以通过宏函数,没有栈帧消耗,在预处理的阶段就被替换了,就没有栈帧的消耗了
平凡的人1
2022/11/15
7900
【C++】内联函数&auto&范围for循环&nullptr
【C++入门篇】学习C++就看这篇--->内联函数、auto关键字、范围for
🚩当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
HABuo
2025/05/23
1160
【C++入门篇】学习C++就看这篇--->内联函数、auto关键字、范围for
相关推荐
C++入门知识(二)
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验