【发布时间】:2014-05-20 20:32:15
【问题描述】:
在 C++ 标准中有来自 3.3.7/1 的引用:
如果对类中的成员声明重新排序会产生一个替代的有效 (1) 和 (2) 下的程序,程序格式错误,没有诊断 必填。
这是什么意思?你能得到一个这样的重新排序声明的例子吗?
【问题讨论】:
-
成员声明的顺序很重要的一个例子是构造。初始化值时,您可能会初始化一个依赖于另一个的值。如果类中的顺序错误,则可能初始化得太早(在其他成员初始化之前)。
在 C++ 标准中有来自 3.3.7/1 的引用:
如果对类中的成员声明重新排序会产生一个替代的有效 (1) 和 (2) 下的程序,程序格式错误,没有诊断 必填。
这是什么意思?你能得到一个这样的重新排序声明的例子吗?
【问题讨论】:
考虑这个程序:
double foo;
class Bar {
std::vector<decltype(foo)> v;
int foo;
};
重新排序 Bar::v 和 Bar::foo 像这样:
double foo;
class Bar {
int foo;
std::vector<decltype(foo)> v;
};
将产生一个在其他方面有效的替代程序,因此该程序违反了引用的规则。
(一个版本的)gcc 选择在第一种情况下发出错误,但使用第二种变体进行编译(“不需要诊断”)。
std::vector<decltype(::foo)> v; 和 std::vector<decltype(Bar::foo)> v; 是有效的替代方案(只有在首先声明 Bar::foo 时才可能使用后者)。
【讨论】:
double foo;
这种情况的一个例子是您在对象构造中可能遇到的常见错误。 代码变体 1 和 2 说明了这一点。 代码变体 1:
class C
{
C() : a1(0), a2(a1)
{
}
int a1;
int a2;
};
代码变体 2:
class C
{
C() : a1(0), a2(a1)
{
}
int a2;
int a1;
};
请注意,在变体 2 中,a1 和 a2 成员声明顺序已更改。好的编译器会对代码变体 2 提供警告:“成员初始化与声明顺序不同”。 问题在于代码变体 2 中的程序行为未定义。一些编译器将生成代码,其中 a2 将以 0 初始化(例如,据我所知,Visual Studio 编译器),一些编译器将生成 a2 值未定义的代码,而在代码变体 1 中,任何编译器都将提供正确的代码。 所以这是你需要的例子。
【讨论】: