Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use C++ class members initialized in the initializer list, later in the list?

I am rewriting some code to eliminate global variables and made a class constructor/destructor handle cleanup of some third party library resources, but I am concerned about some code which initializes one member from another member in the class initializer list.

class MyPodofoDocument {
public:
    // generates pdf to stream
    MyPodofoDocument(std::stringstream *pStringStream)
        : device(pStringStream), document(&device)
    {
    }
private:
    PoDoFo::PdfOutputDevice device;
    PoDoFo::PdfStreamedDocument document;
    PoDoFo::PdfPainter painter;
};

The code which uses this class doesn't need to see all the details that go into using the library, but the way I hide them makes it dependent on using members to initialize other members, before it hits the constructor's actual code block, where it has a valid this pointer.

It works in a unit test skeleton, so my question is basically, "Is this okay, portable and safe?"

like image 874
Kenny Ostrom Avatar asked Feb 19 '13 20:02

Kenny Ostrom


People also ask

When must you use a member initializer list?

Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.

What is the advantage of using member initializer list?

The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.

Can we initialize a class member variable as soon as the same is defined?

The constructors should be used to initialize member variables of the class because member variables cannot be declared or defined in a single statement. Therefore, constructors are used in initializing data members of a class when an object is created.

Does order of initializer list matter?

In the initializer list, the order of execution takes place according to the order of declaration of member variables. While using the initializer list for a class in C++, the order of declaration of member variables affects the output of the program.


2 Answers

The members are initialized in the order they are declared, top to bottom

PoDoFo::PdfOutputDevice device;
PoDoFo::PdfStreamedDocument document;
PoDoFo::PdfPainter painter;

so it is safe to use device to initialize document.

like image 174
Bo Persson Avatar answered Oct 16 '22 13:10

Bo Persson


Kind of. The rules is that the member variables are initialised in the order they are declared in the class declaration.

In your case, it is fine since device is declared before document.

However, in the following case, we have undefined behaviour, despite the order of the initialiser list.

class A {
public:
  A(int i) : b(i), a(b) { }
private:
  int a;
  int b;
}
like image 20
Alex Chamberlain Avatar answered Oct 16 '22 11:10

Alex Chamberlain