c++11是继c++98后的下一个大版本,c++11在vs编译器中是vs2011以后的版本支持,以前的版本支持的不全。
auto(c++11)
auto关键字在c/c++中就有,即auto修饰的变量是具有自动储存器的局部变量,但是没人去用。
因为auto关键字是局部变量前自动补充的。
C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
简单来说就是auto修饰的变量是什么类型的,由给它赋值的变量决定。
int add()
{
return 1;
}
……
int a = 10;
auto b = a;//b的类型为int型
auto c = 'a';//c的类型为char类型
auto d = add();//d的类型为add函数的返回类型
auto的这个过程叫自动推导。
auto修饰变量必须初始化
auto的这个用法只有在支持c++11的编译器上才可以用,不支持c++11的编译器会报错
下面介绍一个可能有用的函数,可以看变量的类型(包括自定义类型)。
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
这是一个用法,记住就行。
打印出:
int
char
int
下面讲解auto的一些比较奇葩的用处
int x = 10;
auto a = &x;
auto* b = &x;//auto加*,代表自动推导的变量必须是地址,传变量会报错
auto& d = x;
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
结果打印出:
int *//int a前加上const,打印出来的是int const*,int const*和const int*是等价的,不同的是int* const
int *
int
auto定义多行变量:
如果出现auto a = 10, b = 200; 这种情况,推导的变量必须为同种类型的变量
如果这样:auto a = 10, b = 'a'; 就会编译失败。因为auto最终还是要被编译器替换为某个具体的变量类型的。
使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型
auto的实际价值:
1.在c++高阶数据结构的容器中简化代码,说的简单一点就是类型很长时就使用auto,交给编译器自动推导。
这个简化代码和typedef存在不同。
2.循环改进方面
void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
array[i] *= 2;
for (int* p = array; p < array + sizeof(array)/ sizeof(array[0]); ++p)
cout << *p << " ";
cout << endl;
}
这是C语言和c++98版本的打印方式
在c++11版本中,可以实现一个叫范围for的用法,针对循环方式进行简化:
void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for(auto e : array)//实现原理:依次自动取array中的内容赋值给e,自动结束。e是变量名,可以随意取。
{
cout << e << " ";
}
cout << endl;
}
这样可以打印出数组array中的数据,即使array中数据增加也可以正常打印。
e只是array中数据的拷贝,对e的改变不会影响数组array中的数据。即:
for(auto e : array)
{
e /= 2;
}
不会导致array中的数据改变。需要对array中数据进行修改的话,需要使用引用
for(auto& e : array)
{
e /= 2;
}
范围for不是一定要用auto实现,指明具体类型也可以实现,比如将上面代码的auto部分替换成int,也可以正常打印。只是范围for习惯使用auto。
范围for,冒号(:)后面必须是数组名,不能用指针。所以这种情况是不能使用的。
void printArr(int arr[])//数组传参后,形参就是指针了//这种情况不行!
{
for(int e : arr)
{
cout << e << " ";
}
cout << endl;
}
auto不能应用的情况:
1. 不能作函数参数 (缺省参数也不行)
2.不能作返回值 //在对特定类型的数据进行处理时,参数类型和返回值类型如果为auto,使用时就不知道传什么样的参数了。
3.不能声明数组 //即这种情况auto b[] = {1 ,2, 3};
nullptr(c++11)
nullptr是c++11中新增的关键字,代表空指针。也就是说指针置空有三种方式。
int* p1 = NULL;
int* p2 = nullptr;
int* p3 = 0;
一般情况下三种是一样的,但是c++中推荐使用nullptr。NULL和0的赋值方式,严格来讲是不规范的。
原因:NULL本质上是宏,在c文件stddef.h中有如下代码
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
在如下情况下使用时:
void f(int)
{
cout<<"f(int)"<<endl;
}
void f(int*)
{
cout<<"f(int*)"<<endl;
}
int main()
{
f(0);
f(NULL);//会调用第一个函数,因为NULL是宏,预处理时被替换成了0,但是NULL想表达的是指针类型
f((int*)NULL);
return 0;
}
c++11为了补这个坑,就定义了nullptr,指((void*)0)