Kundan Kumar
Kundan Kumar

Reputation: 2002

When should we not use initialization list in the constructor?

Can someone please quote an example code when we should not use initialisation list in the constructor and how that can be overcome with assignment?

I am looking for an example for the below statement

This might happen when your class has two constructors that need to initialize the this object's data members in different orders. Or it might happen when two data members are self-referential. Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor's body (when your particular compiler happens to issue that particular warning). Or when you need to do an if/throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members.

Upvotes: 4

Views: 3092

Answers (2)

Fraser
Fraser

Reputation: 78280

Here are some examples:


This might happen when your class has two constructors that need to initialize the this object's data members in different orders.

class Example1 {
 public:
  Example1(std::string decoded, std::string encoded)
      : decoded_(decoded),
        encoded_(encoded) {}
  explicit Example1(std::string encoded)
      : decoded_(),  // Can't use "decoded_(Decode())" since "encoded_" isn't initialised
        encoded_(encoded) {
    decoded_ = Decode();  // Assign here instead of initialising
  }
 private:
  std::string Decode();  // decodes class member "encoded_"
  std::string decoded_, encoded_;
};

In this example, decoded_ will always be initialised before encoded_ since that's the order in which they are declared in the class, even if we swap their order in the initialisation list.


Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor's body (when your particular compiler happens to issue that particular warning).

class Example2 {
 public:
  Example2() : functor_() {
    functor_ = std::bind(&Example2::Do, this);
  }
 private:
  void Do();
  std::function<void()> functor_;
};

Here, functor_ needs to use this when it is initialised/assigned. If we were to intialise functor_ in the initialisation list, the this pointer would be referring to an object which at that point wasn't fully initialised. That could be safe depending on the particular circumstances, but the foolproof option is to defer setting functor_ until inside the constructor body, by which point this does refer to a fully-initialised object.


Or when you need to do an if/throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members.

class Example3 {
 public:
  Example3(int force, int acceleration)
      : force_(force),
        acceleration_(acceleration),
        mass_(0) {
    if (acceleration_ == 0)
      throw std::exception("Can't divide by 0");
    mass_ = force_ / acceleration_;
  }
 private:
  int force_, acceleration_, mass_;
};

Hopefully this is self-explanatory.


I'm not sure what is meant by

when two data members are self-referential

so I can't give an example for that I'm afraid.

Upvotes: 2

AAT
AAT

Reputation: 3386

I believe the main concept that the author of your statement was referring to is the fact that calls made to variables in the initialisation list occur not in the order you see them in the initialisation list, but in the order the variables are listed in the class definition.

That means

  • if you have two different constructors which use initialisation lists, they must initialise them in the same sequence
  • your control over sequencing (which may be important if you have mutually-dependent members) is limited

I'd recommend taking a look at Scott Meyer's Effective C++ which covers this (amongst many, many other useful and informative topics).

Upvotes: 4

Related Questions