views:

3790

answers:

8

I noticed some code of a colleague today that initialized class variables in the initialization. However it was causing a warning, he says because of the order they are in. My question is why is it better to do variable initialization where it currently is and not within the curly brackets?

DiagramScene::DiagramScene( int slideNo, QRectF screenRect, MainWindow* parent )
    : QGraphicsScene( screenRect, parent ),
    myParent( parent ), 
    slideUndoImageCurrentIndex(-1),
    nextGroupID(0),
    m_undoInProgress(false),
    m_deleteItemOnNextUndo(0)
    line(0),
    path(0)
{
    /* Setup default brush for background */
    scDetail->bgBrush.setStyle(Qt::SolidPattern);
    scDetail->bgBrush.setColor(Qt::white);
    setBackgroundBrush(scDetail->bgBrush);

}
+21  A: 
  • It is more efficient (in general). All members of a class are initialised in the constructor, whether you explicitly initialise them or not. If you do not specify an initialiser, then the default constructor of the member is run. If you assign a value in the constructor body, then the assignment operator is called again. This does not apply to scalar values, as in your example, since scalar values do not have constructors.
  • You can't accidentally assign a value twice in the initialiser list.
  • The compiler can check to make sure that the order in which you write the initialisers matches the order in which the members are defined in the class. The C++ standard requires that the members are initialised in the order they are declared, regardless of the order you write the initialisers. Having the compiler check this order ensures that the programmer knows which order the initialisers will be run in (again, this is more important for non-POD members than for scalars).
  • Reference types and const members must be initialised in the initialiser list, because you can't assign to a reference or to a const member.
Greg Hewgill
+2  A: 

Because, in the constructor's body ("within the curly brackets") the member variables are already default-constructed. That may have some performance implications, when you have a member variable of a type that has non-trivial construction, when you first have it default-constructed and then you assign it some other value in the constructor, when you could have custom-construct it directly.

Also, some types may not be default-constructed (for example references) and must be constructed in the initialization list.

Kasprzol
Thanks, added note about references. +1
Greg Hewgill
A: 

Take a look at the collected wisdom at http://web.tiscali.it/fanelia/cpp-faq-en/ctors.html#faq-10.6

Sijin
Ironically this looks like its simply a copy of the C++ FAQ Lite.
Onorio Catenacci
+2  A: 

If you have const variables, their value can not be set via assignment.

The initialization is also a bit more efficient when assigning values to objects (not built-ins or intrinsics) as a temporary object is not created like it would be for an assignment.

See C++ FAQ-Lite for more details

Benoit
+4  A: 

It's better to do the initialization of the members in the initialization list because the members are then only initialized once. This can be a huge difference in performance (and even behavior) if the members are classes themselves. If the members are all non-const, non-reference fundamental data types, then the difference is usually negligible.

NOTE: There are times where initialization lists are required for fundamental data types -- specifically if the type is constant or a reference. For these types, the data can only be initialized once and thus it cannot be initialized in the body of the constructor. See this article for more information.

Note that the initialization order of the members is the order the members are declared in the class definition, not the order the members are declared in the initialization list. If the warning can be fixed by changing the order of the initialization list, then I highly recommend that you do so.

It's my recommendation that:

  • You learn to like initialization lists.
  • Your co-worker understand the rules for initialization order of members (and avoid warnings).
Kevin
+3  A: 

In addition to Greg Hewgill's excellent answer - const variables must be set in the initialisation list.

Dominic Rodger
Thanks, added note about const members. +1
Greg Hewgill
A: 

Another addition to Greg's answer: members that are of types with no default constructor must be initialized in initialization list.

Fred Larson
A: 

Greg Hegwell's answer contains some excellent advice, but it doesn't explain why the compiler is generating a warning.

When the initializer list of a constructor is processed by the compiler, the items are initialized in the order they are declared in the class declaration, not in the order they appear in the initializer list.

Some compilers generate a warning if the order in the initializer list is different from the declaration order (so you won't be surprised when items are not initialized in the order of the list). You don't include your class declaration, but this is the likely cause of the warning you're seeing.

The rationale for this behavior is that the members of a class should always be initialized in the same order: even when the class has more than one constructor (which could have the members ordered differently in their initializer lists).

Stephen C. Steel