39

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
};
4
  • 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? Commented Jun 24, 2012 at 1: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? Commented Jun 24, 2012 at 1:42
  • 3
    The std::vector<double> arr has automatic storage, so there would be an instance of it for each invocation of the function fill_arr. That's basic C++... Commented Jun 24, 2012 at 1:46
  • 1
    It is better to mark fill_arr as const in this example. For readability. Commented Jun 5, 2020 at 13:01

2 Answers 2

42

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
   }
};
Sign up to request clarification or add additional context in comments.

Comments

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.

4 Comments

That's exactly the meat of the question: what are the rules for the construction order for the member functions?
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.
@Zhenya 1st part of sbi's answer (stackoverflow.com/a/3899583/981787 ) is for member functions.
Well, there's his comment to his answer as well... (+1 for the link anyway.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.