C++关键字的C++11详解
用于语法:
asm-definition: asm ( string-literal ) ;
意义由实现定义,典型实现中传输其中的字符串给汇编器。 在C++98/03中这个这个关键字用于声明块中的变量的生存期为自动生存期,若是对象同时具有自动存储类,即生存期在块结束时结束。这样的变量被称为局部变量。这个关键字不常用,因为即便省略,声明的默认就是auto的。
在C++11中,auto的含义改变为自动通过初值符推断声明的类型占位符。如声明auto i = 1;,auto就相当于int,因为1是int类型,可以推断出i的类型。也可以使用auto& i等声明,具体推导规则同模版参数类型推导。 即const_cast、dynamic_cast、reinterpret_cast、static_cast。
C++风格的类型转换。dynamic_cast是动态的,需要运行时支持;其它都是静态检查,相比C风格的类型转换更加细化,增强了类型安全性。 用于类型声明。class是一般的类类型。struct在C++中是特殊的类类型,声明中仅默认隐式的成员和基类访问限定与class不同(struct是public,class是private)。union是联合体类型。满足特定条件类类型——POD struct或POD union可以和C语言中的struct和union对应兼容。
class还有个用途是在模版类型声明中作为表示模版类型参数或模版模版参数的语法的必要组成部分。前者也可被typename代替。 即double、float、long、int、short、signed、unsigned。
signed和unsigned作为前缀修饰整数类型,分别表示有符号和无符号。signed和unsigned修饰char类型,构成unsigned char和signed char,和char都不是相同的类型;不可修饰wchar_t、char16_t和char32_t。其它整数类型的signed省略或不省略,含义不变。signed或unsigned可单独作为类型,相当于signed int和unsigned int。
double和float专用于浮点数,double表示双精度,精度不小于float表示的浮点数。long double则是C++11指定的精度不小于double的浮点数。
其它关键字表示整数类型。从占用空间大小(sizeof)来看,保证char<=short<=int<=long<=long long。注意这些都不是相同的类型,即便大小和范围都一致;各自具有unsigned版本。其中long long是C++11指定的不小于long的整数。 这个关键字修饰构造函数声明,表示显式构造函数(模版),显式构造函数不参与特定的重载。
C++11从两个角度扩展了用法。其一是适用于转换函数(模版),类似构造函数,避免不需要的重载。其二是列表初始化,除非直接使用std::initializer_list,显式构造函数被列表初始化忽略(在C++98/03中,explicit仅对单一参数调用构造函数有意义,这里打破了这个限制)。 extern意为“外来的”,是存储类声明修饰符。这个关键字在C语言中即很不明确,容易被混淆(尤其是extern inline——好在C++没有这种用法)。extern表示被修饰的声明中,名称的链接保持和之前的一致(若已有相同声明存在),或保持默认值(若之前没有相同名称的声明存在)——取决于声明的位置。在命名空间作用域(注意包括全局命名空间),extern表示外部链接;若这里省略extern,则对于const对象,默认具有内部链接;否则表示具有和命名空间一致的链接(若顶层没有嵌套未命名的命名空间,就是外部链接,否则是内部链接)。
C++11新增extern用于模版显式实例化声明,表示不在当前翻译单元实例化模版,而在别处有定义。这可以提升编译效率。 声明定义内联函数(模版),提示编译时内联——将所调用的代码嵌入到主调函数中。注意是否内联取决于实现——编译器有权不实际内联,如果它认为这是必要的或更符合预期的目标代码质量。但inline还改变了ODR(One Definition Rule)的适用性。类似函数模版,在头文件直接定义inline函数不会视为重复定义违反ODR而编译出错。C++中,一个函数若声明inline,则每处声明都必须保证是inline,和C语言允许extern inline或static inline不同——尽管C++实现可以提供类似非标准的扩展。注意类成员函数若在类定义内给出定义则隐含inline。
C++11中,新增inline namespace,指示命名空间中的名称同时是外层命名空间直接包含的名称。这便于命名空间的版本管理,减少冲突。 表示命名空间——其中可以声明若干标识符,组成的名称与其它命名空间不冲突。
可以声明一个命名空间或命名空间别名。 用以给数据类型取别名。字面名义上是定义,实际只是声明——这点和C语言的说法不同。
C++11中可被using新增的用法代替。 告诉编译器一个嵌套的限定名(包含::)中的未知的标识符是一个类型。这只在模板中需要区分依赖名称时使用。
另一种用法是在模版声明参数列表中表示模版类型参数,可被class代替。 有两种基本用法:using声明和using指示(using namespace ...)。
前者是声明,引入命名空间或基类作用域内已经被声明的名称。后者引入命名空间内所有的名称。
C++11新增了一类用法,可以代替typename,同时可以配合template使用(typedef基于语法考虑未被允许加入这种用法)。 特殊的“空”类型,指定函数无返回值或无参数(在参数列表中只能够唯一地使用),用于表达式转换为void类型以丢弃计算值的必要(C++11加入了discarded-value-expression显式地指出了这一点),或用于void*指针类型。