37

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
};
Community
  • 1
  • 1
ev-br
  • 24,968
  • 9
  • 65
  • 78
  • The question is good, but the code sample is somewhat artificial. What prevents you from declaring `fill_arr` as `static` and have no doubt that its legal? – K-ballo Jun 24 '12 at 01:24
  • Would that be thread-safe? I mean, there's a vector local to `fill_arr`, if that's `static`, am I to protect it by a sort of mutex? – ev-br Jun 24 '12 at 01:42
  • 3
    The `std::vector arr` has _automatic storage_, so there would be an instance of it for each invocation of the function `fill_arr`. That's basic _C++_... – K-ballo Jun 24 '12 at 01:46
  • 1
    It is better to mark fill_arr as const in this example. For readability. – E_g Jun 05 '20 at 13:01

2 Answers2

39

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
   }
};
Bojan Komazec
  • 9,216
  • 2
  • 41
  • 51
6

While initializing objects in the initialization list, the object is not yet fully constructed.
If those function tries to access the part of the object which is not yet constructed then that is a undefined behavior else its fine.
see this answer.

Community
  • 1
  • 1
Eight
  • 4,194
  • 5
  • 30
  • 51
  • That's exactly the meat of the question: what are the rules for the construction order for the member functions? – ev-br Jun 24 '12 at 01:03
  • Correct me if I'm wrong: the question you're referring to deals with member variables rather than member functions. Do you imply that member functions follow the same rules? For one, gcc 4.4.3 does not complain if I switch the order of declarations of `arr_` and `fill_arr()`, while it does emit warnings if the order in the init-list is not the same as the order of declarations. – ev-br Jun 24 '12 at 01:18
  • @Zhenya 1st part of sbi's answer (http://stackoverflow.com/a/3899583/981787 ) is for member functions. – Eight Jun 24 '12 at 01:27
  • Well, there's his comment to his answer as well... (+1 for the link anyway.) – ev-br Jun 24 '12 at 01:43