C++之 auto 范围 for nullptr

auto 关键字

auto简介:

什么是auto?

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量

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

看完长叹一声-----喔!没懂,没关系看下面代码,举个栗子

#include<iostream>
#include<stdlib.h>
using namespace std;
int  TestAuto()
{
	return 10;
}
int main()
{
	int a=10;
	auto b=a;
	auto c='s';
	auto d=1.2;
	auto e=TestAuto();
	cout<<typeid(b).name()<<endl;//这个函数用来打印出变量的数据类型,在这里不多
	cout<<typeid(c).name()<<endl;//介绍,以后会详细介绍
	cout<<typeid(d).name()<<endl;
	cout<<typeid(e).name()<<endl;
	system("pause");
	return 0;
}

看一下运行结果:
在这里插入图片描述

在这里插入图片描述
不初始化会报错

大家会觉得auto 似乎可以自动识别类型,假如是 auto d=1.2 编译器就是识别为:double d= 1.2 ;然后好像就是一种类型声明,但是这里需要注意的是:

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

(感觉就是:哎!你要定义并初始化一个变量a=10,但是 int 跑了,好吧我 auto 先帮你占个位子,等到编译器处理的时候,我再和 被编译器找回来的的 int 换下位子 。)

auto使用细则:

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

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

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

运行结果:
在这里插入图片描述
可以看到,由于前两个都是地址所以他的类型是一个指针,而第三个只是给他取了一个别名,访问的还是用一块地址空间所以类型是int 型

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

看一段代码:

int main()
{
	auto a=10,b=12;
	auto c=1.2,d=12;//这里会报一个错
}

在这里插入图片描述
这是为什么呢?
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

3 auto不能推导的场景

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

void TestAuto(auto a)//这里报错
{
//此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导 
}

在这里插入图片描述
2. auto不能直接用来声明数组
在这里插入图片描述
(还是第一次见到这个叫顶级数组的,感觉好高级啊,什么顶级高手,顶级武功秘籍啥的,去百度了一下,还没找到,可能是因为我的编译器是vs2012的吧)

3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
4. auto在实际中常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有lambda表达式等进 行配合使用。
5. auto不能定义类的非静态成员变量(暂不做讲解,后面讲)
6. 实例化模板时不能使用auto作为模板参数(暂不做讲解,后面讲)

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

先看一段代码:

int main()
{
	int arr[10]={0,1,2,3,4,5,6,7,8,9};
	int len=sizeof(arr)/sizeof(arr[0]);
	int i=0;
	for(i=0; i<len; i++)
	{
        cout<<arr[i]<<" ";
	}
	cout<<endl;
	for(auto a : arr)//范围for
	{
		cout<<a<<" ";
	}
	cout<<endl;
	system("pause");
	return 0;
}

看一下运行结果:
在这里插入图片描述
可以看到两个都打印出了数组里的每一个元素

第一种是我们熟悉的for循环,通过控制数组下标和解引用来访问数组里的元素。

第二种是我们的范围for,并结合了我们刚学的auto关键字,那这个是怎么实现的呢?

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

数组 arr 并把数组的内容依次付给 a 然后完成打印,不需要知道数组的大小,交给编译器处理,整个过程是自动识别的,因此十分方便。
注意:范围for与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

2.范围for的使用条件

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

指针空值nullptr(C++11)

我们都知道,以前在c语言的时候,我们表示空的时候都是用NULL来表示的。但是在C++中以后就需要使用nullptr 了,这是为什么呢?
看一段代码:

#include<iostream>
#include<stdlib.h>
using namespace std;
void f(int) 
{  
	cout<<"f(int)"<<endl; 
} 
void f(int*) 
{  
	cout<<"f(int*)"<<endl; 
} 
int main() 
{  
	f(0);  
	f(NULL);  
	f((int*)NULL);
	f(nullptr);
	system("pause");
	return 0; 
}

运行结果:
在这里插入图片描述
这是为什么?因为NULL在头文件里被宏定义为了0 ,而NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。以后在使用时可能会出现歧义。
在这里插入图片描述
为了考虑兼容性,C++11并没有消除常量0的二义性,C++11给出了全新的nullptr表示空值指针。
C++11为什么 不在NULL的基础上进行扩展,这是因为NULL以前就是一个宏,而且不同的编译器厂商对于NULL的实现可能不太相同,而且直接扩展NULL,可能会影响以前旧的程序。
因此:为了避免混淆,C++11提供了nullptr, 即:nullptr代表一个指针空值常量。nullptr是有类型的,其类型为nullptr_t,仅仅可以被隐式转化为指针类 型,nullptr_t被定义在头文件中:

typedef decltype(nullptr) nullptr_t;

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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值