Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do I have to use initializer lists for initializing C++ class members?

let's say I have std::map< std::string, std::string > m_someMap as a private member variable of class A

Two questions: (and the only reason I'm asking is because I came across code like that)

  1. What's the purpose of this line:

    A::A() : m_someMap()
    

    Now I know that this is intialization, but do you have to do this like that? I'm confused.

  2. What's the default value of std::map< std::string, std::string > m_someMap, also C# defines that int, double, etc. is always initialized to defualt 0 and objects are to null (at least in most cases) So what's the rule in C++?? are object initialized by defualt to null and primitives to garbage? Of course I'm taking about instance variables.

EDIT:

also, since most people pointed out that this is a style choice and not necessary, what about:

A::A() : m_someMap(), m_someint(0), m_somebool(false)

like image 571
Tom Avatar asked Oct 27 '09 17:10

Tom


People also ask

When should a constructor use an initializer?

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.

What is an initializer list used for?

The initializer list is used to directly initialize data members of a class. An initializer list starts after the constructor name and its parameters.

Should my constructors use initialization lists or assignment?

Initialization lists. In fact, constructors should initialize as a rule all member objects in the initialization list.


2 Answers

m_somemap

  1. You don't have to.
  2. What you get if you omit it: An empty std::map< std::string, std::string >, i.e., a valid instance of that map which has no elements in it.

m_somebool

  1. You have to initialize it to true or false if you want it to have a known value. Booleans are "plain old data types" and they do not have the concept of a constructor. Moreover, the C++ language does not specify default values for non-explicitly-initialized booleans.
  2. What you get if you omit it: a boolean member with an unspecified value. You must not do this and later use its value. Because of that, it is a strongly recommended policy that you initialize all values of this type.

m_someint

  1. You have to initialize it to some integer value if you want it to have a known value. Integers are "plain old data types" and they do not have the concept of a constructor. Moreover, the C++ language does not specify default values for non-explicitly-initialized integers.
  2. What you get if you omit it: an int member with an unspecified value. You must not do this and later use its value. Because of that, it is a strongly recommended policy that you initialize all values of this type.
like image 99
Daniel Daranas Avatar answered Oct 31 '22 17:10

Daniel Daranas


There is no need to actually do it.
The default constructor will autmatically do it.

But somtimes by making it explicit it acts as sort of documentation:

class X
{
    std::map<string,string>  data;
    Y                        somePropertyOfdata;

    X()
      :data()                    // Technically not needed
      ,somePropertyOfdata(data)  // But it documents that data is finished construction
    {}                           // before it is used here.
};

The rule in C++ is that unless you explicitly initialise POD data it is undefined while other classes have there default constructor called automatically (even if not explicitly done so by the programmer).

But saying that. Consider this:

template<typename T>
class Z
{
     T  data;   
     Z()
        :data()    // Technicall not need as default constructor will
                   // always be called for classes.
                   // But doing this will initialize POD data correctly
                   // if T is a basic POD type. 
     {}
};

Here you would exepect data to be default initialized.
Technically POD do not have constructors so if T was int then would you expect it to do anything? Becuase it was explicitly initialize it is set to 0 or the equivalent for POD types.

For the edit:

class A
{
    std::map<string,string>   m_someMap;
    int                       m_someint;
    bool                      m_somebool;
   public:
    A::A()
       : m_someMap()      // Class will always be initialised (so optional)
       , m_someint(0)     // without this POD will be undefined
       , m_somebool(false)// without this POD will be undefined
    {}
};
like image 39
Martin York Avatar answered Oct 31 '22 18:10

Martin York