【C++11】auto decltype nullptr
文章目录
- Ⅰ. auto
- Ⅱ. decltype
- Ⅲ. nullptr

Ⅰ. auto
在 C++98
中 auto
是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以 auto
就没什么价值了。
所以 C++11
中废弃 auto
原来的用法,将其用于实现自动类型推导。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。
int main()
{
int i = 10;
auto p = &i;
auto pf = strcpy;
cout << typeid(p).name() << endl;
cout << typeid(pf).name() << endl;
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
return 0;
}
易错点:
#include<iostream>
#include<vector>
// 4. vs2013不支持函数形参是auto变量,而qt可以
void func(auto a)
{
//.....
}
// 5. auto变量不能作为自定义类型的成员变量
struct test
{
int a;
auto b=10;
};
int main()
{
// 1. 定义变量时,必须初始化
auto a; // ❌
a = 10;
// 2. 不能是auto数组
auto b[3] = {1, 2, 3}; // ❌
// 3. 模板实例化类型不能是auto类型
std::vector<int> a;
std::vector<auto> b = { 1 }; // ❌
return 0;
}
Ⅱ. decltype
auto
使用的前提是:必须要对 auto
声明的类型进行初始化,否则编译器无法推导出 auto
的实际类型。但有时候可能需要根据表达式运行完成之后结果的类型进行推导,因为编译期间,代码不会运行,此时 auto
也就无能为力。
💡 关键字 decltype
将变量的类型声明为表达式指定的类型。
decltype
实际上有点像 auto
的反函数, auto
可以让你声明一个变量, 而 decltype
则可以从一个变量或表达式中得到其类型!
// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int Fun(int a)
{
return 1;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret = 13.5; // ret的类型是double
decltype(&x) p; // p的类型是int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
-----------------------------------------------------------
// 对于函数指针也可以
int(*pfunc1)(int) = Fun; // 普通的函数指针写法
decltype(&Fun) pfunc2 = Fun;
decltype(pfunc2) pfunc3 = Fun;
cout << typeid(Fun).name() << endl;
cout << typeid(pfunc1).name() << endl;
cout << typeid(pfunc2).name() << endl;
cout << typeid(pfunc3).name() << endl;
-----------------------------------------------------------
F(1, 'a');
-----------------------------------------------------------
auto it = { 1, 2, 3, 4, 5 };
// 如果vector中要存的是自动推导的类型,那么auto是做不到的,因为auto需要初始化,比如vector<auto> v
// 但是我们的decltype则可以通过推导it的类型来构建v
vector<decltype(it)> v;
v.push_back(it);
cout << typeid(it).name() << endl;
cout << typeid(v).name() << endl;
-----------------------------------------------------------
// 匿名类型的枚举变量
enum
{
OK,
ERROR
} flag;
decltype(flag) flag1;
cout << typeid(flag).name() << endl;
cout << typeid(flag1).name() << endl;
return 0;
}
// 运行结果:
double
int const * __ptr64
int __cdecl(int)
int (__cdecl*)(int)
int (__cdecl*)(int)
int (__cdecl*)(int)
int
class std::initializer_list<int>
class std::vector<class std::initializer_list<int>,class std::allocator<class std::initializer_list<int> > >
enum `int __cdecl main(void)'::`2'::<unnamed-type-flag>
enum `int __cdecl main(void)'::`2'::<unnamed-type-flag>
Ⅲ. nullptr
由于 C++
中 NULL
被定义成字面量 0
,这样就可能回带来一些问题,因为 0
既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11
中新增了 nullptr
,用于表示空指针。
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
🔴 注意 nullptr
只能赋值给指针,不能赋值给常量。