C++11的一些新特性
更新日期:
本文的大部分内容翻译自The C++ Standard Library A Tutorial and Reference (2nd Edition)的第三章,书中只列出了一些比较主要的新特性,更多比较详细的C++11特性可以参考C++11FAQ和The C++ Programming Language (4th Edition)。
C++11的新特性
重要的细节语法调整
首先,我想介绍2个C++11中虽然很细节但是对日常编程很重要的新特性。
模板表达式中的空格
原先在模板表达式的2个右括号中间需要加空格,现在不需要了
在整本书(包括实际代码)中,你会发现这2种形式。
nullptr and std::nullptr_t
(空指针和空指针类型)
在C++11中,你可以使用nullptr
表示一个指向空值的指针(注意,这与未定义值不同),而不用再使用0
和NULL
了。这个特性对防止空指针被解释成整形数值的发生特别有用。例如:
nullptr
是新关键字,它可以自动的转换成任意类型的指针但无法转换为整形数值,其类型是std::nullptr_t
,在头文件<cstddef>
中定义。所以,你现在可以重载那些需要传入空指针情况的操作,需要注意的是std::nullptr_t
是一个基本数据类型(see Section 5.4.2, page 127)。
使用auto
自动推断类型
在C++11中,可以使用auto
1声明一个变量或对象而不用指明其具体类型。例如:
使用auto
时,变量的类型是从初始化对象中推断得到的,所以,此时必须对变量做初始化:
也可以使用其他限制符2,例如:
对于表达式长而复杂的类型,auto
非常有用。例如:
上述后半部分表示一个lambda对象,在Section 3.1.10, page 28中会有介绍。
统一的初始化和初始化列表
在C++11之前,程序员,尤其是初学者,很容易对如何初始化一个变量或对象感到困惑。因为初始化可以用括号、大括号以及赋值操作来完成。
基于这个原因,C++11引入了统一初始化的概念,即可以用一个统一的语法完成所有的初始化。这个语法就是使用大括号,如下:
初始化列表强制执行值初始化的操作,也就是说,即使是通常只有未定义值的基础类型的局部变量也会被初始化为0(如果是指针的话,会被初始化为nullptr
)。
但是注意,窄化初始化,即会丢失精度或使用传入对象变化后的值的初始化,是无法使用大括号的。例如:
如上所示,为了检查是否已经应用了窄化,只要编译期可以取值,即使是立即数也需要检查。关于这个例子,正如Bjarne Stroustrup在[Stroustrup:FAQ]中写道:"C++11避免很多不兼容性的方法是当它可以判定初始化对象何处发生了窄化(而非仅仅从类型判定)时,依赖初始化对象的实际值(如上例中的7)。如果传入值可以精确的表示目标值类型的话,这样的类型转换就不是窄化。注意,浮点数转换为整形总是发生了窄化,即使是7.0转换成7这种情况。"
为了能支持用户自定义的初始化列表,C++11提供了类模板std::initializer_list<>
,它可以支持用一组值来执行初始化或者其他任何情况下你希望处理一组值。例如:
当固定参数的构造函数和初始化列表的构造函数同时存在时,初始化列表会被优先考虑:
如果没有初始化列表的构造函数的话,编译器会用2个int
的构造函数初始化q
和s
,而初始化r
的动作是非法的。
由于初始化列表的引入,explicit
与拥有多个参数的构造函数变得更加相关。现在你可以禁止多个传入值情况下的自动类型转换,对使用"="语法的初始化也一样:
相同的情况,参数是初始化列表的explicit
构造函数禁止含一个、多个或为空初始化列表的显式转换。
基于区间的for
循环
C++11引入了新式的for
循环,
cpp
cpp
cpp
cpp
cpp
cpp ```