声明

时间:2024-04-04 17:24:13

auto

在C++11中,新增了关键字auto,其可以自动推导类型:

auto i = 1;//整型
auto d = 3.14;//浮点型
auto p = &i;

此时i就会被自动识别为intd就自动识别为doublep自动识别为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也是用于识别类型的,但是decltypetypeid应用方向不同。

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,其可以转化为很多非指针类型,比如intdoublechar。但是nullptrnullptr_t,它只能转化为其他指针。上述代码中,我们把nullptr转化为一个int,此时编译器会直接报错,绝对禁止这个行为。

但是这样是可以的:

void* p1 = nullptr;
int* p2 = nullptr;
char* p3 = nullptr;
double* p4 = nullptr;

可以看到,nullptr保证了指针类型的稳定,空指针不会被传递到指针以外的类型。因此nullptr在各方面都有足够的优势,以更加安全的形式给用户提供空指针。