1.4.8 融入编程现实

现实世界中的编程往往都有特殊的需求。比如在访问因特网的时候我们常常需要输入URL,而URL通常都包含了斜线“/”。要在C++中输入斜线却不是件容易的事,通常我们需要转义字符“\/”的配合,否则斜线则可能被误认为是除法符号。所以如果读者在写网络地址或目录路径的时候,代码最终看起来就是一堆倒胃口的反斜线的组合,而且会让内容变得晦涩。而C++11中的原生字符串常量则可免除“转义”的需要,也可以帮助程序员清晰地呈现网络地址或文件系统目录的真实内容。

另一方面,如今GNU的属性(attribute)几乎无所不在,所有的编译器都在尝试支持它,以用于修饰类型、变量和函数等。不过attribute((attribute-name))这样的写法,除了不怎么好看外,每一个编译器可能还都有它自己的变体,比如微软的属性就是以__declspec打头的。因此在C++11中,我们看到了通用属性的出现。

不过C++11引入通用属性更大的原因在于,属性可以在不引入额外的关键字的情况下,为编译提供额外的信息。因此,一些可以实现为关键字的特性,也可以用属性来实现(在某些情况下,属性甚至还可以在代码中放入程序供应商的名字,不过这样做存在一些争议)。这在使用关键字还是将特性实现为一个通用属性间就会存在权衡。不过最后标准委员会认为,在现在的情况下,在C++11中的通用属性不能破坏已有的类型系统,也不应该在代码中引起语义的歧义。也就是说,有属性的和没有属性的代码在编译时行为是一致的。所以C++11标准最终选择创建很少的几个通用属性——noreturn和carrier_dependency(其实final、override也一度是热门“人选”)。

属性的真正强大之处在于它们能够让编译器供应商创建他们自己的语言扩展,同时不会干扰语言或等待特性的标准化。它们可以被用于在一些域内加入特定的“方言”,甚至是在不用pragma语法的情况下扩展专有的并行机制(如果读者了解OpenMP,对此会有一些体会)。

我们将在第8章中看到相关的描述。