Initializer list

In previous section, we already know many ways to construct variables. Among these constructors, using initializer list normally is the best ways to construct variables. In this section, we will show you why.

Consider the following case: We have a Line class who has two private members , mStart and mEnd.

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

#define DEBUG true
void log(std::string s) {
  DEBUG && (cout << "[" << __FILE__ << "]" << s << "\n");
}

class Point
{
  friend class Line;
public:
  Point()
  {
    log("Construct Point");
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.mX << ", " << p.mY << ")";
    return out;
  }
private:
  double mX;
  double mY;
};

class Line
{
public:
  Line(double aAx ,double aAy, double aBx, double aBy)
  {
    log("Construct Line");

    mStart.mX = aAx;
    log("Set start point\'s x");
    mStart.mY = aAy;
    log("Set start point\'s y");

    mEnd.mX = aBx;
    log("Set end point\'s x");
    mEnd.mY = aBy;
    log("Set end point\'s y");
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Line& l)
  {
    out << "from " << l.mStart << " to " << l.mEnd;
    return out;
  }

private:
  Point mStart;
  Point mEnd;
};

int main() {
  Line l(1, 2, 3, 4);
  cout << l << endl;
  return 0;
}

The output of above is:

[constructor.cpp]Construct Point
[constructor.cpp]Construct Point
[constructor.cpp]Construct Line
[constructor.cpp]Set start point's x
[constructor.cpp]Set start point's y
[constructor.cpp]Set end point's x
[constructor.cpp]Set end point's y
from (1, 2) to (3, 4)

We can see that we will construct the mStart and mEnd first because they are members. Then, we will need to assign their mX and mY each in Line's constructor.

It's not a good idea if one class has many Point members. It will cost to many instructions to assign the mX and mY.

Instead of assigning after constructing, we can use initializer list to give values for mX and mY when constructing Point members.

#include <iostream>

using std::cout;
using std::endl;
using std::ostream; // for << operator overloading

#define DEBUG true
void log(std::string s) {
  DEBUG && (cout << "[" << __FILE__ << "]" << s << "\n");
}

class Point
{
  friend class Line;
public:
  Point(double aX = 0.0, double aY = 0.0)
    : mX(aX)
    , mY(aY)
  {
    log("Construct Point with init list");
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Point& p)
  {
    out << "(" << p.mX << ", " << p.mY << ")";
    return out;
  }
private:
  double mX;
  double mY;
};

class Line
{
public:
  Line(double aAx ,double aAy, double aBx, double aBy)
  : mStart(aAx, aAy)
  , mEnd(aBx, aBy)
  {
    log("Construct Line with init list");
  }

  // Overwrite the output stream
  friend ostream& operator<<(ostream& out, const Line& l)
  {
    out << "from " << l.mStart << " to " << l.mEnd;
    return out;
  }

private:
  Point mStart;
  Point mEnd;
};

int main() {
  Line l(1, 2, 3, 4);
  cout << l << endl;
  return 0;
}

The output is:

[constructor.cpp]Construct Point with init list
[constructor.cpp]Construct Point with init list
[constructor.cpp]Construct Line with init list
from (1, 2) to (3, 4)

By using initializer list, we can save a lot of instructions to assign value to Point's mX, mY. The mX, mY will be initialize to the corresponding values during constructing the Point members.

Note that it make no difference in POD class members. It's just a matter of style.

References

results matching ""

    No results matching ""