C++11部分新增内容

这学期不再学习C语言了,转向了C++,开始学习面向对象程序设计,也不再以做简单题目,写程序为主,而是学会理顺思路,探索系统的功能实现,转化为各种问题,最终能够自己编写出一套能够切实可行,实现具体功能的系统构架。

C++11新增了很多内容,如constexpr对象auto类型说明符(虽然C++98和C语言中就有auto关键字,用于自动存储类别的局部变量声明,但是并不经常使用,C++11将其完全改版,废除了之前的auto功能并对其进行了重新定义),decltype类型指示符,range for语句等。

我们先来一一介绍一下这些新增内容:

constexpr对象与const对象的关系:
大多数情况下这两种定义在使用上没有区别:
如果认定某个对象是常量表达式,可以把它声明为constexpr类型或const类型,语法上都是可以的。
然后由编译器验证对象的值是否是常量表达式,通过这种方法可以获得编译时常量。
声明的数据对象一定是一个常量,必须用常量表达式初始化。
不同点:
const对象如果作用于全局,编译器会为其分配空间,但是对于constexpr对象如果代码没有明确要使用其地址(编译过程中不涉及到其地址),编译器可以选择不为其分配空间,而仅将其当做编译时期的值(类似于字面值常量)。
或许这样做可以避免调用地址的错误,也可以为程序减少内存量。

auto类型说明符:
auto类型说明符可用于将表达式的数据类型(一般推断该表达式的类型比较困难或不太可能推测)赋给变量,在编译时系统会为其自动匹配数据类型,但是这要求定义auto变量必须有初始值才行。
例:auto x = 5; //5是int类型,所以x是int类型
auto size = sizeof(int); //size的类型是表示内存字节数的类型
auto name = “world”; //name要保存字符串"world"
cout << "hello, " << name; //此时name的类型是什么并不重要,因为并没有使用到name的数据类型,只是将其进行简单的赋值及输出,这也表明当我们对变量的数据类型没有要求或完全不需要知道、不需要用到其数据类型时我们可以考虑使用auto类型说明符去定义。
auto a; //错误:没有初始值,这样系统无法为a匹配数据类型,导致编译错误。
auto r = 1, pi = 3.14; //错误:r和pi推断出的类型不一致,系统并不知道该如何对r,pi匹配数据类型。

decltype类型指示符:
decltype定义与auto定义具有类似的作用,都能返回操作数的类型,但是auto是直接在初始化赋值时将表达式的值直接赋值给变量,具体来说可以说是确定了数据类型并确定了其初始值,但是decltype只是取其数据类型,并不会真的去实际计算表达式的值。
例:decltype(sizeof(int)) size;
//size的类型是sizeof(int)结果(表示内存字节数)的类型,并未对其赋值。
auto size = sizeof(int);
//size的类型是表示内存字节数的类型,且size的初值在数值上等于2/4(具体根据电脑操作系统的位数决定)
auto和decltype的用途:auto和decltype可以让我们不用去记忆和书写复杂的类型名字。

auto和decltype与数组名:
当使用数组名作为一个auto 变量的初始值时,得到的类型是指针而不是数组
decltype(数组名)返回的是数组类型:大小和元素类型
例:
int ia[] = {1, 2, 3, 4, 5};
auto ia2(ia); //ia2 是一个指针,指向ia 的第一个元素
//等同于:int* ia2 = ia;
ia2 = 42; //错误:ia2 是指针,不能用int 值给指针赋值

decltype(ia) ia3 = {6, 7, 8, 9, 10};
//ia3 是一个包含5 个元素的int 数组;
//ia3 和ia 同样:数组大小和元素类型
ia3 = p; //错误:不能用指针给数组赋值
ia3[2] = 5; //正确:可以给数组元素用int 赋值

range-for语句 :
rang-for是一种简化的for语句,从头至尾对容器或序列的所有元素逐个执行某种操作(遍历)
其定义形式如下:
for( declaration : expression )
statement;

expression是要处理的序列
初始值列表、数组、vector或string等类型的对象
declaration定义一个变量,表示序列中的每个元素
statement是一条语句或语句块,表示对元素的处理代码
例:
int arr[] = {1, 3, 5, 7, 9};
for(auto ele : arr) {
ele = ele * 2;
cout << ele << " ";
} // 输出:2 6 10 14 18
不过使用range-for时,需要注意:
在范围for语句块内不能改变正在遍历的序列的大小,例如不能向序列中加入元素或删除元素。