112

Is it good practice when writing C++11 code to set default values for class members in the header file of the class?

Or is it better to do this in the constructor of the class?

EDIT:

I mean:

foo.h:

#include <string>

using std::string;

class Foo{
    private:
        string greet = "hello";
    public:
        Foo();
};

VS

foo.cpp (of course with the necessary header file, but without the in-class initialization):

Foo::Foo(){
    greet = "hello";
}

Which one is better and why?

Paul
  • 20,883
  • 7
  • 57
  • 74
  • 2
    What do you mean in the header file? C++11 in-class member initialization? A code sample of both cases would help illustrate. – chris Jul 21 '12 at 18:32
  • 1
    @chris updated with code samples. – Paul Jul 21 '12 at 18:49
  • Those two samples do different things, so certainly the first one is better. Search for _member initialization list_ – K-ballo Jul 21 '12 at 19:09
  • 6
    using clauses in header should be avoided – vlad_tepesch Feb 22 '16 at 15:52
  • 2
    A bit late, I know – you should use constructors initialisation list: `Foo::Foo() : greet("hello") { }` – this avoids default initialisation + assignment in favour of direct initialisation by value. For complex types, this can make a significant difference, more important, though: Some types (references, constant members, non-default constructible ones) *only* can be initialised that way (in the constructor, apart from assigning a default). – Aconcagua Feb 19 '20 at 09:43

3 Answers3

123

If a class member is always initialized with the same initial value, then you should make the initializer inline, so as to avoid duplication. If the initial value depends on the constructor, then put it in the constructor initializer list. (And never use assignment in the way you did.)

Example:

class Foo
{
    bool done = false;   // always start like this
    int qty;
    Bar * p;

public:
    Foo()                        : qty(0),              p(nullptr)    { }
    Foo(int q, Bar * bp)         : qty(q),              p(bp)         { }
    explicit Foo(char const * s) : qty(std::strlen(s)), p(new Bar(s)) { }

    // ...
};

In this hypothetical example, the member done is always required to start as false, so it's best to write the initializer inline. The other two members, qty and p, can be initialized differently in each of three different constructors, so they are initialized inside the constructors' initializer lists.

A curiosum: Note that providing an inline initializer prevents your class from having a trivial default constructor.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
13

It depends whether you need to stay compatible with older C++ compilers .When you are not using C++11 you have to initialize most members (all non-static) in the constructor. Further many people advocate to explicitly initialize every member even if this means explicitly calling the default ctor. Usually you should place implementation details in a cpp file not in the header file, thus an example would be

Example:
//foo.h

class Foo{
public: 
  Foo();
private:
  std::vector<int> vect;
};

//foo.cpp

Foo::Foo():vect(){
}

In C++11 you have more choices and in class member initializer will become very handy, especially if you have several cors. Here is a good link for more information: http://www.stroustrup.com/C++11FAQ.html#member-init

After Edit: According to your code you are using C++11. To my knowledge there is only few information on good practice concerning the new possibilities but IMHO In class member initializer are very handy to concentrate initialization in one place, which reduces complexity and typing

Bulletmagnet
  • 5,665
  • 2
  • 26
  • 56
Martin
  • 4,738
  • 4
  • 28
  • 57
  • Yeah, I updated my question to better reflect what I meant, I mostly agree with you on "reduces complexity and typing". – Paul Jul 21 '12 at 18:49
5

Initializing in headers has the main advantages of keeping code more local and easy to understand. It saves also some typing.

The main disadvantage, in my opinion, is the need to include more headers to get access to constructors. Simple forward declaration won't suffice, making compilation take longer.

Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85