auto
在C++11中,新增了关键字auto
,其可以自动推导类型:
auto i = 1;//整型
auto d = 3.14;//浮点型
auto p = &i;
此时i
就会被自动识别为int
,d
就自动识别为double
,p
自动识别为int*
。
auto
的主要作用在于对于有一些类型,它的长度太长了,我们就可以用auto
一笔带过。
比如完整地定义一个迭代器:
vector<int> v;
vector<int>::iterator it = v.begin();
但是我们可以用auto
直接自动识别:
vector<int> v;
auto it = v.begin();
在定义迭代器的时候,auto
的使用还是比较常见的。
decltype
在C++11以前,有一个关键字typeid
,其可以识别一个类型,并且可以通过name
成员函数来输出类型名。
比如这样:
int i = 0;
int* pi = &i;
cout << typeid(i).name() << endl;
cout << typeid(pi).name() << endl;
输出结果为:
int
int * __ptr64
也就是说,我们可以通过typeid
来检测甚至输出变量类型。
而decltype
也是用于识别类型的,但是decltype
与typeid
应用方向不同。
decltype
可以检测一个变量的类型,并且拿这个类型去声明新的类型
比如这样:
int i = 0;
decltype(i) x = 5;
decltype(i)
检测出i
的类型为int
,于是decltype(i)
整体就变成int
,从而定义出一个新的变量x
。
nullptr
在C++11后,推出了新的空指针nullptr
,明明已经有NULL
了,为啥还需要nullptr
?
NULL
在C语言中,表示的是((void*)0)
,也就是被强制转为void*
类型的0。但是在C++中,NULL
就是整数0
比如可以用刚才学的typeid
验证一下:
cout << typeid(NULL).name() << endl;
输出结果为:int
,这下就石锤了NULL
在C++中就是int
。
这会导致不少问题,比如这样:
void func(int x)
{
cout << "参数为整型" << endl;
}
void func(void* x)
{
cout << "参数为指针" << endl;
}
int main()
{
func(NULL);
return 0;
}
以上代码中,func
函数有两个重载,一个是参数为指针,一个是参数为整型。我现在就是想传一个空指针去调用指针版本的func
。但是最后还是会调用int
类型的。
而nullptr
不一样,nullptr
不仅不是整型,而且其也不是void*
。C++给了nullptr
一个专属类型nullptr_t
。这个类型有一个非常非常大的优势,该类型只能转化为其它指针类型,不能转化为指针以外的类型。
比如以下代码:
int x1 = NULL;//正确
int x2 = nullptr;//错误
因为NULL
本质是0,其可以转化为很多非指针类型,比如int
,double
,char
。但是nullptr
是nullptr_t
,它只能转化为其他指针。上述代码中,我们把nullptr
转化为一个int
,此时编译器会直接报错,绝对禁止这个行为。
但是这样是可以的:
void* p1 = nullptr;
int* p2 = nullptr;
char* p3 = nullptr;
double* p4 = nullptr;
可以看到,nullptr
保证了指针类型的稳定,空指针不会被传递到指针以外的类型。因此nullptr
在各方面都有足够的优势,以更加安全的形式给用户提供空指针。