【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)

在这里插入图片描述

个人主页:@Weraphael
✍作者简介:目前学习C++和算法
✈️专栏:C++航路
希望大家多多支持,咱一起进步!
如果文章对你有帮助的话
欢迎 评论 点赞 收藏 加关注✨


前言

本章是补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的。

目录

  • 前言
  • 一、auto关键字
    • 1.1 问题引入
    • 1.2 auto简介
    • 1.3 auto的使用细则
    • 1.4 常见auto不能推导的场景
    • 1.5 基于范围的for循环(重点)
      • 1.5.1 遍历数组
      • 1.5.2 用auto修改数组元素
    • 1.6 范围for的使用条件
  • 二、 指针空值nullptr

一、auto关键字

1.1 问题引入

随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:
1. 类型难于拼写(过长)
2. 含义不明确导致容易出错

来看看以下代码:

#include 
#include 
#include 
using namespace srd;

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

以上代码刚刚对于C++初学者可能看不懂,而std::map::iterator 是一个类型还是看的出来的吧,但由于该类型太长了,写的也累。所以有些人可能想:可以通过typedef给这么长的类型取别名

例如:

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

使用typedef给类型取别名确实可以简化代码,可能会引起以下问题:

  1. 难以理解:typedef可以创建新的类型名称,但可能会使代码难以理解和维护。如果类型名称太过简略或不符合命名规范,会导致代码的可读性降低。
  2. 可能会与其他定义冲突:由于typedef允许用户创建新的类型名称,因此可能会与其他定义发生冲突。这可以通过遵循命名规则和避免使用与其他名称相同的名称来避免。
  3. 难以进行调试:由于typedef创建了新的类型名称,因此调试时可能会难以确定变量的类型。这可以通过良好的代码注释和为类型名称选择有意义的名称来避免。
  4. 可能会导致错误:typedef也可以用于创建指向其他类型的指针或引用类型。如果不小心使用了错误的类型名称,可能会导致程序错误。这可以通过在代码中进行仔细的检查和测试来避免。

因此,C++11给auto赋予了新的含义。

1.2 auto简介

在早期auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,但遗憾的是它使用的一点也不频繁。因此,C++11中标准委员会赋予了auto全新的含义:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器它可以通过赋值操作符右边的表达式来推导出其类型。

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第1张图片

typeid可以打印变量类型

1.3 auto的使用细则

1. auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*没有任何区别

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第2张图片

但用auto声明引用类型时则必须加&

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第3张图片

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

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第4张图片

96行代码会编译失败,因为c和d的初始化表达式类型不同。

1.4 常见auto不能推导的场景

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

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第5张图片

此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导

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

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第6张图片

1.5 基于范围的for循环(重点)

1.5.1 遍历数组

  • 普通方法遍历数组

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第7张图片

对于普通的遍历,我们需要先求出数组大小。而对于auto遍历,却缺少了这一步,让我们继续往下看

  • auto遍历数组

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第8张图片

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。它本质的意思是:依次取数组arr中的元素赋值给e

1.5.2 用auto修改数组元素

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第9张图片

对于auto修改数组元素,要运用到引用,相当于对arr取别名

1.6 范围for的使用条件

1. for循环迭代的范围必须是确定的
2. 迭代的对象要实现++和==的操作

二、 指针空值nullptr

在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下方式对其进行初始化:

#include 
#include 

using namespace std;

int main()
{
	int* p = NULL;
	int* pp = 0;

	return 0;
}

NULL实际是一个宏,在传统的C头文件(stddef.h)中,我们通过查询cplusplus网站来查看其属性

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第10张图片

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第11张图片

  • 程序本意是想通过NULL调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。
  • 这是因为在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void*)NULL
    【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第12张图片
    C++11引入了nullptr,因此可以不用强转NULL
    【C++入门】auto关键字(C++11) + 指针空值nullptr(C++11)_第13张图片
    但需要注意的是:
  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

你可能感兴趣的:(C++,c++,学习,c语言,visualstudio,auto)