25.1.2 实现问题
编写C++(www.cppentry.com)编译器时,编译器的设计者试图遵循C++(www.cppentry.com)标准。遗憾的是,C++(www.cppentry.com)标准有一千多页长,混合了文字叙述、语言语法和示例。两个根据这样的标准实现一个编译器的人都不可能以完全相同的方式解释标准中每一条信息,也不可能处理每一个边缘情况。因此,编译器会有bug。
1. 编译器的怪异特性和扩展
没有简单的规则能发现或避免编译器bug。您能做的最好的就是保持编译器最新,或订阅编译器的邮件列表或新闻组。如果您怀疑遇到了一个编译器bug,可以在网上简单地搜索您看到的错误消息或条件,有可能能找到解决方法或补丁。
编译器产生麻烦最臭名昭著的一个方面是语言最初始标准中没有的扩充。例如,C++(www.cppentry.com)中有一些模板和运行时类型的特性最初不是标准的一部分,因而一些编译器仍然没有加入这些特性。使用C++(www.cppentry.com)11中的新特性的时候您也会遇到同样的问题。并非所有编译器都支持每个新功能。
另一个要注意的问题是,编译器通常包括自己对语言的扩展,而没有让程序员清楚地了解这些扩展。例如,基于堆栈的大小可变数组不是C++(www.cppentry.com)语言的一部分,但下面的代码在使用g++编译器编译的时候能按照期望的那样编译和运行:
- int i = 4;
- char myStackArray[i]; // Not a standard language feature!
- 代码取自VariableArray\VariableArray.cpp
一些编译器扩展可能是有用的,但是如果某个时候您需要切换编译器,那么您应该检查编译器是否处于禁用了这些扩展的严格模式。例如,编译以上代码的时候向g++传入-pedantic标志会得到以下警告消息:- warning: ISO C++(www.cppentry.com) forbids variable length array 'myStackArray' [-Wvla]
C++(www.cppentry.com)规范允许通过#pragma机制使用特定类型的编译器定义的语言扩展。#pragma是一个预编译指令,这条指令的行为时由编译器的实现定义的。如果某个实现不理解这条指令,则会忽略这条指令。例如,有些编译器允许程序员通过#pragma暂时关闭编译器的警告。
2. 库的实现
您的编译器多半实现了一个C++(www.cppentry.com)标准库,包括标准模板库。然而,由于STL是用C++(www.cppentry.com)编写的,因此并不要求您使用编译器自带的那个STL。例如,您可以使用一个针对速度优化的第三方STL,甚至可以编写自己的STL。
当然,STL实现者与编译器编写者面临着同样的问题-- 标准的实现受到对标准解释的影响。此外,某些实现可能作出权衡,而这种权衡可能不符合您的需求。例如,一个实现可能针对速度优化,而另一个实现则可能关注于让容器尽可能使用少的内存。
使用STL实现或任何第三方库的时候,重要的是要考虑设计者在开发过程中所做的权衡。第2章更详细地讨论了使用库的时候遇到的问题。