OK, member variables can be used to initialize other member variables in an initialization list (with care taken about the initialization order etc). What about member functions? To be specific, is this snippet legal according to the C++ standard?
struct foo{ foo(const size_t N) : N_(N), arr_(fill_arr(N)) { //arr_ = fill_arr(N); // or should I fall back to this one? } std::vector<double> fill_arr(const size_t N){ std::vector<double> arr(N); // fill in the vector somehow return arr; } size_t N_; std::vector<double> arr_; // other stuff };
To initialize a class member variable, put the initialization code in a static initialization block, as the following section shows. To initialize an instance member variable, put the initialization code in a constructor.
Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.
It probably refers to in-class member initializers. This allows you to initialize non-static data members at the point of declaration: struct Foo { explicit Foo(int i) : i(i) {} // x is initialized to 3.1416 int i = 42; double x = 3.1416; }; More on that in Bjarne Stroustrup's C++11 FAQ.
Static Data Member Initialization in C++ We can put static members (Functions or Variables) in C++ classes. For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator, then the variable name.
Yes, your use of member function in initialization list is valid and complies with the standard.
Data members are initialized in the order of their declaration (and that's the reason why they should appear in the initialization list in the order of their declaration - the rule that you followed in your example). N_
is initialized first and you could have passed this data member to fill_arr
. fill_arr
is called before constructor but because this function does not access uninitialized data members (it does not access data members at all) its call is considered safe.
Here are some relevant excepts from the latest draft (N3242=11-0012) of the C++ standard:
§ 12.6.2.13: Member functions (including virtual member functions, 10.3) can be called for an object under construction.(...) However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result of the operation is undefined. Example:
class A { public: A(int); }; class B : public A { int j; public: int f(); B() : A(f()), // undefined: calls member function // but base A not yet initialized j(f()) { } // well-defined: bases are all initialized }; class C { public: C(int); }; class D : public B, C { int i; public: D() : C(f()), // undefined: calls member function // but base C not yet initialized i(f()) { } // well-defined: bases are all initialized };
§12.7.1: For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior. Example
struct W { int j; }; struct X : public virtual W { }; struct Y { int *p; X x; Y() : p(&x.j) { // undefined, x is not yet constructed } };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With