考虑以下(简化)的情况:
class Foo
{
private:
int evenA;
int evenB;
int evenSum;
public:
Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)
{
}
};
当我实例化美孚这样的:
Foo foo(1,3);
然后evenA为0,evenB为2,但将evenSum被初始化为2?
我想这是我目前的平台(iOS)上,它似乎工作,但我不知道该代码是否是便携式的。
谢谢你的帮助!
这是明确的和便携式的,1,但它的潜在的容易出错。
成员在他们班上身体,而不是他们的初始化列表中列出的顺序声明的顺序初始化。 所以,如果你改变类主体,该代码可能默默地消失(尽管许多编译器会发现这一点,并发出警告)。
1.从[class.base.init]在C ++标准(S):
在一个非委托构造函数,以下列顺序进行初始化:
- 第一,只对最派生类(1.8)的构造,虚基类在它们出现在基类的有向无环图,其中“的深度优先左到右的遍历顺序左初始化到右”是在派生类基础说明符列表的基类的出现的顺序。
- 然后,直接基类中声明的顺序,因为它们出现在基本符列表(不管MEM-初始化的顺序)进行初始化。
- 然后,非静态数据成员在他们的类定义中声明 (再次不管MEM-初始化的顺序) 的顺序进行初始化 。
- 最后,执行构造函数体的复合语句。
(突出显示是我的。)
标准的这一部分随后前进到给使用成员变量初始化其他成员变量的一个例子。
是的,提供他们已经被构建。 但不要忘记,施工顺序是声明在类定义,在构造函数中初始化的不是订单的订单。 而且,如果你使用一个变量已建成之前,它的编译器通常不会告诉你。 在你的情况,例如,如果移动evenSum
到类的顶部,你有不确定的操作(因为它的初始化使用未初始化的成员),即使在构造函数中,初始化evenA
和evenB
前词汇evenSum
。
成员在他们的类定义声明的顺序初始化。 只要你的初始化列表如下这个命令,它应该没问题。
这也没有错误编上G ++ 4.0.3(现在6岁)。
我深信,这将汇编任何合理最近的编译器的罚款。
文章来源: Can member variables be used to initialize other members in an initialization list?