1
Non-static data members of classes are usually initialized by the class's
2
constructors. Frequently (but not always) the same initializations are used by
3
different constructors, resulting in multiple points where the initializations
4
are performed, which in turn complicates class maintenance.
6
Consider a class defining several data members: a pointer to data, a data
7
member storing the number of data elements the pointer points at, a data
8
member storing the sequence number of the object. The class also
9
offer a basic set of constructors, as shown in the following class interface:
17
static size_t s_nObjects;
21
Container(Container const &other);
22
Container(Data *data, size_t size);
23
Container(Container &&tmp);
26
The initial values of the data members are easy to describe, but somewhat
27
hard to implement. Consider the initial situation and assume the default
28
constructor is used: all data members should be set to 0, except for tt(d_nr)
29
which must be given the value tt(++s_nObjects). Since these are
30
em(non)-default actions, we can't declare the default constructor using tt(=
31
default), but we must provide an actual implementation:
40
In fact, em(all) constructors require us to state the
41
tt(d_nr(++s_nObjects)) initialization. So if tt(d_data)'s type would have been
42
a (move aware) class type, we would still have to provide implementations for
43
all of the above constructors.
45
The C++11 standard, however, supports emi(data member initializers),
46
simplifying the initialization of non-static data members. Data member
47
initializers allow us to assign initial values to data members. The compiler
48
must be able to compute these initial values from initialization expressions,
49
but the initial values do not have to be constant expressions. So
50
tt(++s_nObjects) can be an initial value.
52
Using data member initializers for the class tt(Container) we get:
58
size_t d_nr = ++nObjects;
60
static size_t s_nObjects;
63
Container() = default;
64
Container(Container const &other);
65
Container(Data *data, size_t size);
66
Container(Container &&tmp);
69
Note that the data member initializations are recognized by the compiler,
70
and are applied to its implementation of the default constructor. In fact, all
71
constructors will apply the data member initializations, unless explicitly
72
initialized otherwise. E.g., the move-constructor may now be implented like
75
Container(Container &&tmp)
83
Although tt(d_nr)'s intialization is left out of the implementation it
84
em(is) initialized due to the data member initialization provided in the