Well this is not as much as something that I dont know how to implement, but more something that I dont know why I would want to implement it.

When I have a simple class, say this one:

class Cube
{
    public:
        Cube(int x, int y, int z);
        int return_area();

    private:
        int width;
        int height;
        int other;
};

The way that I would normaly expand my functions would be like this:

Cube::Cube(int x, int y, int z)
{
    width = x;
    height = y;
    other = z;
}

int Cube::return_area()
{
    return width * height * other;
}

But recently, in one of my many C++ learning books, the sample code in the book was more like this:

class Cube
{
public:
    Cube(int x, int y, int z): width(x), height(y), other(z) {}

    // all the other code 
};

They both have the same effect of asigning a value to the Cube's varaibles but does this second way have something extra? Is there a reason I should rather use the first way than the second (vice versa)?

Dani AI

Generated

Short answer: prefer the initializer list in most real code, but understand why. As and already pointed out, initializer lists do more than cosmetic sugar — they control how objects are constructed, and that can affect correctness, performance and even whether your code compiles.

Two important rules that often get missed:

  • Members are constructed in the order they are declared in the class, not the order you list them in the initializer list. If one member depends on another, a mismatched order can cause subtle bugs; many compilers warn about this mismatch.
  • Base classes (virtual bases first) are constructed before non-static data members. That affects what state is available when a member is built.

Practical consequences:

  • For class-type members, using the initializer list constructs them directly with the right arguments. Assigning inside the constructor body causes default construction first, then assignment, which can be slower and requires a default constructor to exist. This is why objects without default constructors (and const or reference members) force you to use an initializer list.
  • Since C++11 you can give members inline default initializers in the class. A constructor initializer list overrides those defaults; if you omit both, the inline default (if present) is used. Delegating constructors and helper functions can be used to compute complex initial values while still keeping initialization correct.

Quick guidance: always explicitly initialize every member (use initializer lists for non-trivial types), keep the initializer list order matching declaration order, use sensible in-class defaults for primitives or resource handles, and only assign in the constructor body when you must perform conditional or expensive setup after basic construction. The points from and are the right baseline; these extra rules help avoid the common pitfalls.

Recommended Answers

All 3 Replies

The second constructor there is using an initialisation list. There's no difference in the final state of the object when it's finished.

If any of your member variables were const, or references, the initialisation list would be the only way to set the values. It's also usually faster to use an initialisation list, especially if any member variables are not primitive types.

A couple of observations:

  1. C++ classes have member initializers which should be used OUTSIDE of the main block of the constructor. IE, do this:

    Cube::Cube(int x, int y, int z)
    : width(x), height(y), other(z)
    {
    }

Why? Because you always want your member variables initialized before you can use them. Once you are inside the main block of the constructor, you can use them, initialized or not - BOOM!

So, your second example is correct. If you submitted the first example as an exercise or exam product in one of my classes, you would have been seriously downgraded for that... :-)

All that said, ALWAYS use the initialization list to set your member variables to some sane default value. Ones that require more complex work to set properly - that CAN be done inside main, but ONLY after you have set a proper default value, even if it is a flag that it wasn't properly initialized for the domain of the class. An example of this might be a file descriptor. Valid values are >= 0. So, if your class has a member that is a file descriptor, initialize it to -1. That way, you can tell easily that it is not something you want to perform I/O on... :-)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.