98用太久,学习下11,根据网上资料的知识总结。
1. 编译器推断出来的auto类型有可能和初始值类型不同。
对于顶层const,auto会忽略顶层const性质(除非显式声明为const);但是decltype是会保留下来的。
const int i = 6;
auto a = i;// int a = i;
const auto b = i;// const int b = i;
decltype (i)c = i;// const int c = i;
a = 8;
b = 9;// 非法
c = 10;// 非法
2. decltype的结果类型与表达式形式有密切关系。
比如decltype()内层没有括号,那么得到的类型就是变量的类型;如果有多层括号decltype(())那么返回的就是引用。
int i = 6;
decltype (i)a = i;// int a = i
decltype ((i))b = i;//int b & = i;
a = 8;
b = 9;// i值也跟着变
3. auto是通过编译器计算变量的初始值来推断类型的,而decltype是通过编译器分析表达式来得到它的类型,它不用将表达式的值计算出来。
4. decltype的出现是为了弥补auto不支持对于表达式的类型推导的缺陷, 适用于后置返回类型的推导。
auto func = [](int a, double b) -> decltype(a + b)
{
return a + b;
};
5. auto和decltype都可以用于新的for循环语法糖
5.1 表达式
for(declaration: expression){
//循环体
}
declaration表示是要定义一个变量,这个变量的类型要和即将被遍历的序列中的元素类型一致,可以使用auto或者decltype来进行定义,让编译器自动做类型的推导。
expression表示遍历的序列,可以是数组、容器甚至可以是一个大括号初始化的序列。
5.2 与普通的for循环相比,基于范围的循环方式是“自明”的。
这种语法构成的循环不需要额外的注释或语言基础,很容易就可以看清楚它想表达的意义。在针对容器做遍历的情况,使用这种循环方式让编码和维护变得更加简便。
5.3 代码示例
char mychar[] = "hello world!";
for (decltype ('c') s : mychar) {
cout << s;
}
cout << "end"<<endl;
std::map<std::string, int> mymap =
{
{ "1", 1 },{ "2", 2 },{ "3", 3 }
};
for (auto& val : mymap)
{
std::cout << val.first << " -> " << ++val.second << std::endl;
}
运行结果:
注意:遍历字符串的时候,不仅仅遍历到最后一个字符,而且还会遍历位于该字符串末尾的'\0'。
当容器是set时,由于内部元素是只读的,for循环中 auto& 会被推导为 const int&。