在某些情况下,例如所描述的情况,C++ 标准允许编译器以客户认为最有用的任何方式处理构造,而不要求行为是可预测的。换言之,此类构造调用“未定义行为”。然而,这并不意味着这样的结构是“禁止的”,因为 C++ 标准明确放弃了对“允许”格式良好的程序做什么的管辖权。虽然我不知道任何已发布的 C++ 标准基本原理文档,但它描述未定义行为的事实与 C89 非常相似,这表明其预期含义是相似的:“未定义行为使实现者许可不捕获某些困难的程序错误进行诊断。它还确定了可能的符合语言扩展的区域:实现者可以通过提供官方未定义行为的定义来扩充语言。
在很多情况下,最有效的处理方式是编写结构中下游代码会关心的部分,同时省略下游代码不关心的部分。要求程序初始化结构的所有成员,包括那些永远不会关心的成员,会不必要地影响效率。
此外,在某些情况下,让未初始化的数据以不确定的方式表现可能是最有效的。例如,给定:
struct q { unsigned char dat[256]; } x,y;
void test(unsigned char *arr, int n)
{
q temp;
for (int i=0; i<n; i++)
temp.dat[arr[i]] = i;
x=temp;
y=temp;
}
如果下游代码不关心x.dat 或y.dat 的索引未在arr 中列出的任何元素的值,则代码可能会优化为:
void test(unsigned char *arr, int n)
{
q temp;
for (int i=0; i<n; i++)
{
int it = arr[i];
x.dat[index] = i;
y.dat[index] = i;
}
}
如果要求程序员在复制 temp.dat 的每个元素(包括下游不关心的那些元素)之前显式编写它,那么效率的提高是不可能的。
另一方面,在某些应用程序中,避免数据泄露的可能性很重要。在这样的应用程序中,有一个版本的代码可能很有用,该版本被检测为捕获任何复制未初始化存储的尝试,而不考虑下游代码是否会查看它,或者有一个实现保证任何存储可能很有用其内容可能被泄露的内容将被归零或被非机密数据覆盖。
据我所知,C++ 标准并没有试图说这些行为中的任何一个都比另一个更有用,以证明强制它是合理的。具有讽刺意味的是,这种缺乏规范可能旨在促进优化,但如果程序员不能利用任何类型的弱行为保证,任何优化都将被否定。