9.4.2 未经指定的行为
C++(www.cppentry.com)留下的程序结构的行为中至少有6个是未经指定的,然而,存在这类未经定义行为的C++(www.cppentry.com)实现却会执行任何可能的操作;于是,ANSI/ISO C++(www.cppentry.com)标准给出了当结构的行为是未经指定时可能执行的行为列表。另外,C++(www.cppentry.com)实现也没有必要用文档说明当在程序中碰到这类未经指定行为时会执行哪种操作。
例如,函数参数的求解顺序就是未经指定的。因此,考虑下面给定的print_args。函数的定义:
- void print_args(int arg1, int arg2){
- cout << arg1 << arg2 << endl;
- return;
- }
如果我们如下调用print_args:- int i = 0;
- print_args(++i, i);
那么输出结果可能是: - 1 0
也可能是:- 1 1
而C++(www.cppentry.com)编译器并不需要说明它将产生哪个结果;不仅如此,函数调用不同,同一个实现的行为也可能是不同的。
定义在不同翻译单元的全局对象的初始化顺序也是未经指定的。C++(www.cppentry.com)语言未能指定这个顺序往往会给程序库编写者带来许多困难。12.1节将会更详尽地讨论这个问题,以及程序库作者可以为初始化执行什么样的操作。
依赖于未经指定的行为的程序在被构建和执行的时候偶尔也会照预期地运行。例如,假设我们的程序包含了两个翻译单元f和g,并且还包含了一个初始化依赖性,即只有当定义在f的全局变量的初始化时间比定义在g的全局变量的初始化时间早,程序才能准确无误地运行。那么假设我们如下链接这个程序:
- % link f.obj g.obj
如果我们的编译系统拥有这样的特性:翻译单元中全局变量的初始化顺序和链接命令中指定的翻译单元的顺序一样,那么当用这个编译系统创建程序时,我们的程序就可以准确无误地运行。然而,当我们要把我们的程序移植到具有不同编译系统的平台,并且在这个平台运行这个程序的时候,程序的行为就在所难料了。
因此,对于那些旨在编写可移植代码的C++(www.cppentry.com)程序员,要有小心谨慎的态度,才能避免依赖于这类未经指定的行为。