1.类型推导:auto
C ++11引入了 auto 和 decltype 关键字实现类型推导,通过这两个关键字不仅能方便地获取复杂的类型,而且还能简化书写,提高编码效率。 C11中 auto 成为类型指示符( type - specifier )。在C语言中叫存储类型指示符。
auto 类型推导: auto 定义的变量,可以根据初始化的值,在编译时推导出变量名的类型。
注意:1)最好auto 与变量是一对一的,如果不是要注意初始化的类型要一致,否则容易出现二义性
2)推演auto的类型的时候,如果给出了几个✳,那么auto所指的类型中就相应的少几个✳,
3)使用auto时必须初始化。才能推断出auto的类型,并且替换掉。
void main()
{
auto a = 10;//10->x->int .auto=int;
auto dx = 12.21;
auto fx = 12.3f;
auto ch = 'a';
auto x = 5;//x->int auto->int
const auto* xp = &x;//xp->const int* auto->const int
auto ip = &x;//ip->int * auto->int *
auto* sp = &x;//sp->int* auto->int
}
由上面的例子可以看出来, auto 并不能代表一个实际的类型声明(如 s 的编译错误),只是一个类型声明的"占位符"。
使用 auto 声明的变量必须要有初始化值,以让编译器推断出它的实际类型,并在编译时将 auto 占位符替换为真正的数据类型。
auto的推导规则 从上面的示例中可以看到 auto 的一些使用方法。它可以同指针、引用结合起来使用,还可以带上 cv 限定符( cv - qualifier (修饰词), const 和 volatile 限定符的统称)。
一旦数据的类型出现了const那么auto一定出现const
void main()
{
const int a = 10;
auto b = a;//b->int auto->int
auto& c = a;//因为a是常变量,所以c->const int& auto->const int
}
auto不能推导的场景
1)auto不能作为函数的参数
auto不能作为形参类型,因为编译器无法对a的实际类型进行推导,只有在调用函数的时候,才会进行传参,在这之前不知道auto类型的话,栈帧的大小,以及给a变量分配空间的大小都不知道,在编译的时候就会报错。
2)auto不能作为函数的返回值,但可以接收函数返回值
3)auto不能用来声明数组
2.类型推导:declttype
上一节所讲的 auto ,用于通过一个表达式在编译时确定待定义的变量类型, auto 所修饰的变量必须被初始化,编译器需要通过初始化来确定 auto 所代表的类型,即必须要定义变量。若仅希望得到类型,而不需要(或不能)定义变量的时候应该怎么办呢?
C ++11新增了 decltype 关键字,用来在编译时推导出一个表达式的类型。 它的语法格式如下: decltype ( exp ) 其中, exp 表示一个表达式( expression )。 从格式上来看, decltype 很像 sizeof -﹣用来推导表达式类型大小的操作符。类似于 sizeof ,
int my_add(int a, int b)
{
return a + b;
}
void main()
{
int x = 10;
decltype(x) y = 1;//根据推演出的x的类型来定义y
decltype(x) a;//不赋值也是可以的 ,因为decltype只是获取类型
decltype(x + y) z = 10;//同样不会去计算x+y 而是得到类型给z初始化
const int& x = 10;
decltype(x) j = 20;//推导出x的值是const int &
int z = 10;
const decltype(z)* p = &z;//p->const int *
decltype(z)* ip = &z;//ip->int *
decltype(my_add(1,2)) z;//不会去调用该函数,只是得到函数返回值就可以了
}
3.基于范围的for循环
在C98中,不同的容器和数组,遍历的方法不尽相同,写法不统一,也不够简洁,而 C ++11基于范围的 for 循环以统一、简洁的方式来遍历容器和数组,用起来更方便了。 在 C ++中遍历一个数组(容器)的方法一般是这样的以下是基于范围的 for 循环的一般格式:
for ( ElemType val : array )
{
...//statement 循环体
}
ElemType :是范围变量的数据类型。它必须与数组(容器)元素的数据类型一样,或者是数组元素可以自动转换过来的类型。
val :是范围变量的名称。该变量将在循环迭代期间依次接收数组中的元素值。在第一次循环迭代期间,它接收的是第一个元素的值;在第二次循环迭代期间,它接收的是第二个元素的值;以此类推。
array :是要让该循环进行处理的数组(容器)的名称。该循环将对数组中的每个元素迭代一次。不能对指针进行迭代,指针不是集合的概念
statement :是在每次循环迭代期间要执行的语句。要在循环中执行更多的语句,则可以使用一组大括号来包围多个语句。与其他循环体一样,可以用 continue 来结束本次循环,也可以用 break 来跳出整个循环。
总结:这个for循环是创建变量接收每个数组或容器中的值,所以对变量的改变不会影响到数组或容器本身,但是如果要改变数组或容器的值就要去使用引用。
void main()
{
int ar[] = { 1,2,3,4,5,6,7,8 };
for (int x : ar)
{
cout << x << " ";
x += 10;
}
cout << endl;
for (int x : ar)
{
cout << x << " ";
}
cout << endl;
for (int &x : ar)//引用
{
cout << x << " ";
x += 10;
}
cout << endl;
for (int x : ar)
{
cout << x << " ";
x += 10;
}
cout << endl;
}
4.基于范围的for循环和auto
void main()
{
int ar[] = { 12,23,34,45,56,67,78 };
char str[] = { 'a','b','c','d' };
double dx[] = { 1.2,2.3,3.4,4.5 };
for (auto x : ar)
{
cout << x << " ";
}
cout << endl;
for (auto y : str)
{
cout << y << " ";
}
cout << endl;
for (auto d : dx)
{
cout << d << " ";
}
cout << endl;
}