基类初始化器和成员变量初始化器的顺序重要吗
Does the order of base-class initializers and member variable initializers matter?
类构造函数的初始值设定项的顺序是否重要?
所以说我有:
class MyClass : BaseClass
{
int a, b, c;
public:
MyClass(int);
}
例如1:
MyClass::MyClass(int forBase) :
a(7),
b(14),
c(28),
BaseClass(forBase) { }
例如2:
MyClass::MyClass(int forBase) :
BaseClass(forBase),
a(7),
b(14),
c(28) { }
示例1会做与示例2不同的事情吗?
示例1会做与示例2不同的事情吗?
否。初始化顺序由标准决定,而不是由编写初始化程序的顺序决定:
[C++11: 12.6.2/10]:
在非委托构造函数中,初始化按以下顺序进行:
- 首先,并且仅对于最派生类(1.8)的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中"从左到左"是基类在派生类基类说明符列表中的出现顺序
- 然后,直接基类按照它们在基说明符列表中出现的声明顺序进行初始化(无论mem初始化器的顺序如何)
- 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,与mem初始化程序的顺序无关)
- 最后,执行构造函数主体的复合语句
事实上,如果你以任何其他顺序写它们,并且其中一个依赖于另一个,你很可能会被警告:
struct T {
std::vector<int> v;
int w;
T(int w) : w(w), v(0, w) {}
};
int main() {
T t(3);
}
// g++ 4.1.2:
// t.cpp: In constructor 'T::T(int)':
// Line 3: warning: 'T::w' will be initialized after
// Line 2: warning: '__gnu_debug_def::vector<int, std::allocator<int> > T::v'
// Line 5: warning: when initialized here
顺序对编译器来说并不重要(初始化顺序始终是基类优先,基类按派生顺序,成员按声明顺序),但对读者来说很重要:如果初始化程序的执行顺序与它们的执行顺序不匹配,那将非常令人困惑。虽然在大多数情况下这并不重要,但在某些情况下,你可以创建微妙的错误,例如
struct Derived: Base
{
int member;
Derived();
}
Derived::Derived():
member(3),
Base(member) // This is executed *before* member is initialized!
{
}
如果初始化程序的顺序正确,这个错误会更加突出:
Derived::Derived():
Base(member), // Now we see immediately that member is uninitialized
member(3),
{
}
在构造函数初始化列表中按哪个顺序列出初始化项并不重要。成员按照声明的顺序进行初始化,基在成员之前进行初始化。
但是,如果子对象的初始值取决于其他子对象的值,则以不同的顺序列出初始值设定项可能会影响您。
class A
{
int y, x;
A(int x_value): x(x_value), y(x) {}
};
由于y是在x之前初始化的,所以它会得到一个垃圾值,初始化器列表的顺序只会隐藏错误。这就是为什么这值得编译器警告的原因。
相关文章:
- lambda 作为接受其他参数的参数的初始化顺序
- 大括号或等于初始值设定项初始化顺序
- C++ 模板中的静态常量初始化顺序
- 视觉C++:在 DLL 加载期间,全局变量初始化顺序是否具有确定性?
- 销毁 pthread 互斥体和 C++ 中的取消初始化顺序
- 线程局部变量的初始化顺序
- 类静态变量初始化顺序
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- 解析 CRTP 初始化顺序
- 内联初始化的静态 const 类成员的初始化顺序保证
- 使用constexpr的全局初始化顺序
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- 为什么结构属性声明和初始化顺序的行为是这样的?
- 影响初始化顺序(以C++为单位)
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- C++11 成员类初始化顺序
- 同一函数中的静态函数变量初始化顺序
- 静态内联成员初始化顺序
- C++静态初始化顺序:添加到映射中
- 静态成员的静态阵列:初始化顺序惨败的可能性