Does the order of base-class initializers and member variable initializers matter?

流过昼夜 提交于 2019-12-18 07:19:57

问题


Is the order of the initializers for a class' constructor significant?

So say I have:

class MyClass : BaseClass
{
      int a, b, c;

   public:
      MyClass(int);
}

e.g. 1:

MyClass::MyClass(int forBase) :
  a(7),
  b(14),
  c(28),
  BaseClass(forBase) { }

e.g. 2:

MyClass::MyClass(int forBase) :
  BaseClass(forBase),
  a(7),
  b(14),
  c(28) { }

Would example 1 do something different to example 2?


回答1:


Would example 1 do something different to example 2?

No. Initialisation order is dictated by the standard, not by the order in which you write the initialisers:

[C++11: 12.6.2/10]: In a non-delegating constructor, initialization proceeds in the following order:

  • First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
  • Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
  • Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
  • Finally, the compound-statement of the constructor body is executed.

In fact, if you write them in any other order and one depends on the other, you may well be warned about it:

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



回答2:


The order does not matter for the compiler (the initialization order is always base classes first, and always base classes in the order of derivation, and members in the order of declaration), but it does matter for the reader: It is very confusing if the order in which you give the initializers does not match the order in which they are executed. While in most cases it doesn't matter, in some cases you can create subtle bugs, e.g.

struct Derived: Base
{
  int member;
  Derived();
}

Derived::Derived():
  member(3),
  Base(member) // This is executed *before* member is initialized!
{
}

This bug would stand out more clearly if the initializers were given in the correct order:

Derived::Derived():
  Base(member), // Now we see immediately that member is uninitialized
  member(3),
{
}



回答3:


It doesn't matter in which order you list the initializers in the constructor initialization list. Members are initialized in the order they are declared and base(s) are initialized before members.

However, listing initializers in a different order that that can bite you if a subobject's initial value depends on the values of other subobjects.

class A
{
  int y, x;
  A(int x_value): x(x_value), y(x) {}
};

Since y is initialized before x, it gets a garbage value, and the order of the initializer list just hides the bug. That's why this deserves a compiler warning.



来源:https://stackoverflow.com/questions/8854354/does-the-order-of-base-class-initializers-and-member-variable-initializers-matte

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!