C++学习笔记——auto/decltype 自动推导类型
Posted 火山上的企鹅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++学习笔记——auto/decltype 自动推导类型相关的知识,希望对你有一定的参考价值。
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::map<int, std::string> m = 1,"a", 2,"b"; // 自动推导不出来
auto iter = m.begin(); // 自动推导为map内部的迭代器类型
auto f = bind1st(std::less<int>(), 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 <<endl; //s2的值是 234567
//③遍历 + 常引用(只读)"
string s3 = "123456";
for(const auto& i : s3) // 常引用方式访问元素,避免拷贝代价
// i ++; //报错
cout << i; // 常引用不会改变元素的值
cout<<"," << s3 <<endl; //s3的值是 123456
打印结果:
为了保证效率,最好使用 “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<int>; // 集合类型别名
private:
set_type m_set; // 使用别名定义成员变量
// 使用decltype计算表达式的类型,定义别名
using iter_type = decltype(m_set.begin());
iter_type m_pos; // 类型别名定义成员变量
;
● 学习的课程和书籍:
《罗剑锋的 C++ 实战笔记》
《C++ Primer Plus 第六版》
以上是关于C++学习笔记——auto/decltype 自动推导类型的主要内容,如果未能解决你的问题,请参考以下文章
C++11新特性:3—— C++ decltype类型推导完全攻略