C++11 新增了一个工具,让编译器能够根据初始值的类型判断变量的类型:自动类型推导(auto/decltype)
● auto 初识
auto x = 0L; // 自动推导为long auto y = &x; // 自动推导为long* auto z {&x}; // 自动推导为long* int max_len = 1024; auto ptr = (int*)(&max_len ); // 自动推导为int* auto i = 0; // 自动推导为int类型 auto x = 1.0; // 自动推导为double类型 auto str = "hello"; // 自动推导为const char [6]类型 std::mapm = {{1,"a"}, {2,"b"}}; // 自动推导不出来 auto iter = m.begin(); // 自动推导为map内部的迭代器类型 auto f = bind1st(std::less (), 2); // 自动推导出类型,具体是啥不知道 auto err; // 错误,没有赋值表达式,不知道是什么类型
在类成员变量初始化的时候,目前的 C++ 标准不允许使用 auto 推导类型
class X final { auto a = 10; // 错误,类里不能使用auto推导类型}; }
记住两条简单的规则:
● auto 总是推导出“值类型”,绝不会是“引用”;
● auto 可以附加上 const、volatile、*、& 这样的类型修饰符,得到新的类型。
如下:
auto x = 10L; // auto推导为long, x是long auto& x1 = x; // auto推导为long, x1是long& auto* x2 = &x; // auto推导为long,x2是long* const auto& x3 = x; // auto推导为long,x3是const long& auto x4 = &x3; // auto推导为const long*,x4是const long*
优点总结:
1、避免未初始化变量。因为 auto 必须初始化才能使用
2、使代码简洁
3、避免了对类型的“硬编码”,定义类型更加灵活
再补充:auto的对应类型不是使用new出来的变量,也不是static变量,auto变量在函数结束时即释放了,再次调用这个函数时,又重新定义了一个新的变量。
● auto 最佳实践
在 “range-based for” 中,不需要关心容器元素类型、迭代器返回值和首末位置,就能非常轻松地完成遍历 *** 作:
void autoTest() { //① 遍历 + 写 string s1 = "123456"; for (auto i : s1 ) { //普通方式改变访问 i ++; //改变字符串的每个字符, 不会改变整个字符串 s2 cout << i ; } cout<<"," << s1 << endl; //s1的值是 123456 //② 遍历 + 写 + 引用 string s2 = "123456"; for (auto& i : s1 ) { //引用方式访问元素 i ++; //改变字符串的每个字符, 使用引用会改变整个字符串 s1 cout << i ; } cout<<"," << s1 <打印结果:
为了保证效率,最好使用 “const auto&” 常引用 或者 “auto&” 引用。
● decltype 初识
int x = 0; // 整型变量 decltype(x) x1; // 推导为int,x1是int decltype(x)& x2 = x; // 推导为int,x2是int&,引用必须赋值 decltype(x)* x3; // 推导为int,x3是int* decltype(&x) x4; // 推导为int*,x4是int* decltype(&x)* x5; // 推导为int*,x5是int** decltype(x2) x6 = x2; // 推导为int&,x6是int&,引用必须赋值decltype 不仅能够推导出值类型,还能够推导出引用类型,也就是表达式的“原始类型”。
就是写起来略麻烦,初始化的时候,表达式要重复两次(左边的类型计算,右边的初始化),把简化代码的优势完全给抵消了,所以一般情况使用 auto 。
● decltype 最佳实践:
当你感觉“这里我需要一个特殊类型”的时候,选 decltype 就对了。
比如说,定义函数指针在 C++ 里一直是个比较头疼的问题,因为传统的写法实在是太怪异了。但现在就简单了,你只要手里有一个函数,就可以用 decltype 很容易得到指针类型。
// UNIX信号函数的原型,看着就让人晕,你能手写出函数指针吗? void (*signal(int signo, void (*func)(int)))(int) // 使用decltype可以轻松得到函数指针类型 using sig_func_ptr_t = decltype(&signal) ;另外一个是在类中使用,因为 auto 不能在定义类的时候使用:
class DemoClass final { public: using set_type = std::set; // 集合类型别名 private: set_type m_set; // 使用别名定义成员变量 // 使用decltype计算表达式的类型,定义别名 using iter_type = decltype(m_set.begin()); iter_type m_pos; // 类型别名定义成员变量 };
● 学习的课程和书籍:
《罗剑锋的 C++ 实战笔记》
《C++ Primer Plus 第六版》
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)