【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针)

这篇具有很好参考价值的文章主要介绍了【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr


目录

一. 前言

二. auto关键字

2.1 auto的引入

2.2 auto简介

2.3 auto的使用细则

2.4 auto不能推导的场景

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

3.1 范围for的语法

3.2 范围for的原理

3.3 范围for的使用条件

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


一. 前言

        上期我们介绍了c++新增的两个重要语法:引用和内联函数,今天我们带来的内容是auto关键字范围for以及nullptr指针,本期也是初识C++的最后一期。上期回顾:

【C++深入浅出】初识C++中篇(引用、内联函数)http://t.csdn.cn/LCvY0        话不多说,直接上菜!!!

二. auto关键字

2.1 auto的引入

        在我们写代码的过程中,可曾发现,随着程序越来越复杂,程序中用到的类型也越来越复杂,包括但不限于以下两点:1. 类型难于拼写、2. 含义不明确导致容易出错。例如:

#include <string>
#include <map>
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>::iterator 其实是一个类型,是不是非常吓人【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr。像这种长类型特别容易写错,有的人可能已经想到了解决方案:可以通过typedef给类型取别名。是的,这无疑也是种好方法,但使用typedef前我们必须先知道类型,有时候这并不容易做到。那怎么办呢?不急,C++11中的auto关键字就是为了解决这个问题。

2.2 auto简介

        在早期C/C++中使用auto修饰的变量,是具有自动存储器的局部变量,但由于用处不大,一直没有人去使用它。

        而在C++11中,C++标准委员会赋予了auto全新的含义,即auto不再是一个存储类型指示符,而是作为一个新的类型指示符指示编译器,使用auto声明的变量类型编译器会在编译时期自动推导而得。

        为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法。

#include<string>
int TestAuto()
{
	return 10;
}
int main()
{
	int a = 10;
	string s;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
	auto e = s.begin();
	cout << typeid(b).name() << endl; //typeid类似于sizeof一样,是一个操作符,其可以用来获取变量的类型。
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	cout << typeid(e).name() << endl;
	//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
	return 0;
}

输出结果如下【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr 

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

可以看出,编译器自动帮我们将类型推导出来了,是不是非常方便【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

2.3 auto的使用细则

        学会了auto的基本使用,接下来就是避坑时间惹【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr 

        1. auto定义变量时必须对其进行初始化

         auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”。在编译阶段编译器需要根据初始化表达式来推导auto的实际类型,然后将auto替换为变量实际的类型。

int main()
{
	int val = 10;
	auto a; //错误写法,编译时会报错
	auto b = val; //正确写法,定义时进行初始化,编译器才能进行推导然后将auto替换
	return 0;
}

        2. auto和指针和引用

        用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须
加&

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;
	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	*a = 20;
	*b = 30;
	c = 40;
	return 0;
}

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

         3. 在同一行定义多个变量

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

int main()
{
	auto a = 1, b = 2; // 正确写法
	auto c = 3, d = 4.0; // 编译失败,因为c和d的初始化表达式类型不同

	return 0;
}

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

2.4 auto不能推导的场景

        1、auto不能作为函数的参数

// 此处代码编译失败,auto不能作为形参类型,
// 原因:函数调用传参发生在运行阶段,故在编译阶段编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

        2.、auto不能直接用来声明数组

int main()
{
	int a[] = { 1,2,3 };
	auto b[] = { 4,5,6 };
	return 0;
}

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr


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

3.1 范围for的语法

        在C++98中如果要遍历一个数组,可以按照以下方式进行:

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
	{
		array[i] *= 2; //利用下标访问
	}
	cout << endl;
	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
	{
		cout << *p << ' '; //利用指针访问
	}
	cout << endl;

}

        但是对于array这个有范围的集合而言,由程序员来说明循环的范围显然显得有点多余,有时候还会容易犯错误产生越界。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号分为两部分:第一部分是范围内迭代取得的变量,第二部分则表示进行迭代的集合对象。上述代码使用范围for改写如下【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto& e : array) //依次取数组的数据给引用变量e,自动判断结束,自动迭代 + 1
	{
		e *= 2;
	}
	for (auto e : array) //依次取数组的数据赋值给变量e,自动判断结束,自动迭代 + 1
	{
		cout << e << " ";
	}
	return 0;
}

可以看到,我们使用到了之前学的auto关键字,利用auto的自动类型推导,我们无需显式地写出e的类型,使得范围for的使用更加简洁方便,这也是auto的常见优势用法之一。


在第一个范围for中,由于e是引用变量,因此e表示的是数组每个元素的别名,对e进行修改就是对数组元素进行修改。

而在第二个范围for中,e是普通变量,表示的是数组每个元素的拷贝,对e进行修改对数组元素没有影响。


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

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr


3.2 范围for的原理

        可能会有的小伙伴会好奇:范围for这个东西这么智能,既能自动迭代,还能自动判断结束,那么它的原理究竟是什么呢【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr 

         实际上,并没有想象中的那么复杂。范围for的底层原理实际上就是迭代器遍历编译器在编译时会自动将范围for的代码替换为迭代器遍历相关代码。迭代器的知识我们后续会介绍,这里大家将其理解为指针即可。

        下面是一段vector容器的遍历代码:

int main()
{
	vector<int> v;
	for (int i = 1; i <= 5; i++) //插入1-5的数据
	{
		v.push_back(i);
	}

	for (auto e : v) //范围for遍历
	{
		cout << e << ' ';
	}
	cout << endl;
	return 0;
}

       编译器编译时范围for会替换成类似于如下的代码:

int main()
{
	vector<int> v;
	for (int i = 1; i <= 5; i++) //插入1-5的数据
	{
		v.push_back(i);
	}

	vector<int>::iterator it = v.begin();
	//auto it = v.begin(); //迭代器的类型较长,也可以使用auto自动推导

	while (it != v.end()) //迭代器遍历,这里将it当做指针理解即可
	{
		cout << *it << ' ';
		it++;
	}
	cout << endl;
	return 0;
}

结论:范围for其实就是编译器进行了替换,本质上还是迭代器的遍历

3.3 范围for的使用条件

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

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

void putArray(int array[])
{
	//数组传参发生降维,array是个指针,指向数组首元素
	for (auto e : array) //由于array只是个int*指针,我们无法确定迭代的范围,故这里的范围for会报错
	{
		cout << e << ' ';
	}
}
int main()
{

	vector<int> v;
	for (int i = 1; i <= 5; i++) //插入1-5的数据
	{
		v.push_back(i);
	}

	for (auto e : v) //范围for遍历vector容器类。范围:v.begin()~v.end()
	{
		cout << e << ' ';
	}
	cout << endl;

	int array[5] = { 1,2,3,4,5 };
	for (auto e : v) //范围for遍历array数组。范围:从第一个元素的下标0到最后一个元素的下标4
	{
		cout << e << ' ';
	}

	putArray(array);
	return 0;
}

        2、迭代的对象要实现++和==的操作

        上面我们看到范围for替换为迭代器遍历的代码中,使用迭代器it进行遍历时需要用到++和==的操作,顾迭代器需要支持++和==的操作。(目前不清楚的了解一下即可,等到我们讲解迭代器时再深入讨论)


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

        在C语言中,我们对指针进行初始化时,经常会用NULL空指针进行初始化,如下:

int main()
{
	int* p1 = NULL;
	return 0;
}

         实际上,NULL是一个,在传统的C头文件(stddef.h)中,可以看到如下代码:

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

        可以看到,NULL在C++中被定义为字面常量0,在C语言中被定义为无类型指针(void*)常量。而字面常量0在编译器看来默认是整形常量,这就会导致出现一些不可预料的错误,例如:

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;
}

        上述代码在C++中的结果如下所示【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

本意我们是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL在C++中被定义成字面常量0,因此调用了更符合的f(int)函数,与程序的初衷相悖。如果我们执意要调用f(int*)函数,只能将NULL强制类型转换为int*,再进行调用即可,但这样会显得非常奇怪【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr 


        出于以上原因,C++11新增了一个关键字nullptr用来表示指针空值,如下:

void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}
int main()
{
	f(0);
	f(nullptr); //nullptr表示空指针
	return 0;
}

        此时代码的结果就符合我们初衷了:【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针),C++深入浅出,c++,开发语言,auto关键字,范围for,nullptr

关于nullptr的几点说明与建议 

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

以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏文章来源地址https://www.toymoban.com/news/detail-678333.html

到了这里,关于【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在疯狂三月之后,深入浅出分析AIGC的核心价值 (下篇)|【AI行研&商业价值分析】

    Rocky Ding 公众号:WeThinkIn 【AI行研商业价值分析】栏目专注于分享AI行业中最新热点/风口的思考与判断。也欢迎大家提出宝贵的优化建议,一起交流学习💪 大家好,我是Rocky。 本文是《在疯狂三月之后,深入浅出分析AIGC的核心价值》系列的第二篇文章,在第一篇文章中,我

    2024年02月16日
    浏览(42)
  • 从C语言到C++(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for +nullptr

    目录 1. 内联函数 1.1 内联函数的概念 1.2 内联函数的特性 1.3 宏的优缺点和替代方法 2. auto(C++11) 2.1 改版前的auto 2.2 C++11的auto 2.3 auto 的使用场景 2.4 使用auto的注意事项 3. 范围 for(C++11) 3.1 范围 for 的用法 3.2 范围 for 的使用条件 4. 指针空值 nullptr 4.1 C++ 98 中的指针空

    2023年04月21日
    浏览(47)
  • 深入浅出C++ ——线程库

      在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了 原子类 的概念。要使用标准库中

    2024年02月03日
    浏览(70)
  • 深入浅出C++——C++的类型转换

    在C语言中,如果 赋值运算符左右两侧类型不同 ,或者形参与实参类型不匹配,或者 返回值类型与接收返回值类型不一致 时,就需要发生类型转化。 C语言中总共有两种形式的类型转换: 隐式类型转换:编译器在编译阶段自动进行转换,不能转就编译失败。 显式类型转换:

    2024年02月07日
    浏览(56)
  • 深入浅出C++ ——C++11

        1998年是C++标准委员会成立的第一年,本来计划以后每5年视实际需要更新一次标准,C++国际标准委员会在研究C++ 03的下一个版本的时候,一开始计划是2007年发布,所以最初这个标准叫C++07。但是到06年的时候,官方觉得2007年肯定完不成C++ 07,而且官方觉得2008年可能也

    2024年02月02日
    浏览(58)
  • 【C++深入浅出】日期类的实现

    目录 一. 前言  二. 日期类的框架 三. 日期类的实现 3.1 构造函数 3.2 析构函数 3.3 赋值运算符重载 3.4 关系运算符重载 3.5 日期 +/- 天数 3.6 自增与自减运算符重载 3.7 日期 - 日期 四. 完整代码          通过前面两期类和对象的学习,我们已经对C++的类有了一定的了解。本期我

    2024年02月07日
    浏览(60)
  • 【C++】模板初阶 【 深入浅出理解 模板 】

    如何实现一个通用的交换函数呢? 使用函数重载虽然可以实现 ,但是有一下几个不好的地方: 重载的函数 仅仅是类型不同 ,代码复用率比较低, 只要有新类型出现时,就需要用户自己增加对应的函数 代码的可维护性比较低,一个出错可能所有的重载均出错 那能否 告诉编

    2024年02月05日
    浏览(59)
  • 【C++】深入浅出STL之vector类

    文章篇幅较长,越3万余字,建议电脑端访问 大家好,在上一文中,我们重点介绍了 STL中的string类,明白了如何去操作字符串。 本文我们将要来介绍的是STL中的vector类 vector的文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元

    2024年02月13日
    浏览(53)
  • 【C++】深入浅出STL之string类

    文章篇幅较长,越7万余字,建议电脑端访问 本文我们就要来说一说STL中的string类,这也是我们在写C++代码的时候使用最多的 首先要来谈的一点就是为什么要学习string类 string 意为字符串,那回忆一下我们在C语言阶段所学习的字符串,是以 \\\'\\0\\\' 结尾的一些字符的集合,为了操

    2024年02月15日
    浏览(87)
  • 【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

    【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针 大家好,今天是【重学C++】系列的第二讲,我们来聊聊C++的智能指针。 在上一讲《01 C++如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不小心,就会导致内

    2024年02月05日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包