2

In a Code::Blocks v13.12 project I have a class called Drawable which has a floating point member variable called rotation.

I noticed that explicitly declaring rotation inside Drawable's default constructor would trigger the following warning:

'Drawable::rotation' should be initialized in the member initialization list [-Weffc++]

However, explicitly declaring rotation alongside its definition doesn't do this.

What I want to know is, why does this:

Drawable() {
    rotation = 0.f;
}

Give me a member initialization warning, while this:

class Drawable
{
    ...
    float rotation = 0.f;
    ...
}

And this:

Drawable() : rotation(0.f) {}

Compile without complaint?

Bryn McKerracher
  • 683
  • 6
  • 21

1 Answers1

4

The -Weffc++ warning are described as follows:

Warn about violations of the following style guidelines from Scott Meyers' Effective C++ series of books:

  • Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
  • Prefer initialization to assignment in constructors.
  • Have operator= return a reference to *this.
  • Don't try to return a reference when you must return an object.
  • Distinguish between prefix and postfix forms of increment and decrement operators.
  • Never overload &&, ||, or ,.

The warning you are seeing is covered in Item 4: Make sure that objects are initialized before they’re used of Effective C++ 3rd edition which says (paraphrased):

The rules of C++ stipulate that data members of an object are initialized before the body of a constructor is entered.

and:

A better way to write the [...] constructor is to use the member initialization list instead of assignments [...] constructor yields the same end result [...] but it will often be more efficient.

and (emphasis my wording):

The assignment-based version first called default constructors to initialize the member variables then promptly assigned new values on top of the default-constructed ones. All the work performed in those default constructions was therefore wasted. The member initialization list approach avoids that problem,

In C++11 in class member initializers (which also avoids this warning) can simplify initialization if most of your member variables have default values, the one disadvantage is that until C++14 this make your class a non-aggregate.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • I don't understand the "will often be more efficient". Does C++, if their is no explicit initialization - add code to initialize a float to 0? – Scooter Jan 06 '15 at 03:38
  • @Scooter it is a *guideline* so there are cases such as built-in type where there won't be a cost. The point is to build good habits such as always listing every data member in the member initialization list which avoids unintialized member variables which could lead to undefined behavior. – Shafik Yaghmour Jan 06 '15 at 04:06
  • @Scooter the guideline exists for at least 2 reasons: (1) because `rotation` may one day be something more complex than a float, and you would not want to default-construct an object only to have it overwritten immediately afterwards. (2) because it is bad practice to have uninitialised variables available to program logic. In the future someone maintaining your class may assume that `rotation` has been initialised when it has not, causing a subtle logic error. The fact that you are asking whether it is initialised or not is an indication that a maintainer will be confused. – Richard Hodges Jan 06 '15 at 09:00