Class constructors and data member initialization

I recently discovered the new - new to me anyway! - feature of modern C++ that allows you to set the initial value of a data member when you declare it:

1
2
3
4
class CINTWrapper{
private:
    int m_iData=0;
};


This even extends to calling member functions that help with initialization I believe:

1
2
3
4
5
6
class CStringWrapper{
private:
    wchar_t* Allocate_Array(const int iBufferSize);

    wchar_t* m_pString=Allocate_Array(1);
};


At first, this seemed an extremely useful piece of functionality that C++ had been lacking all along. However, the more I thought about it the more it struck me this feature actually undermines one of the principle design elements of the language - that being the Constructor.

As I understand it the primary purpose of the Constructor is specifically to give the programmer a place where it is guaranteed he can always initialize his data members before anything else is done with the class. However, given the new initialization rules this is no longer necessary. So it largely seems to me that Constructors as a whole are no longer necessary either! I do appreciate Copy-Constructors are a special and vital case. Admittedly when I was using them for their intended purpose I hated either the redundancy you had to introduce across multiple Constructors; those with and without arguments and so on, or alternately the fine tuning of helper-functions to do common initialization between these variants. Now however I sort of regret this cast-iron rule has been taken away.

As a last point, I am trying to change the way I think about programming. I am trying to employ more objects than pure C-style ('int' or 'double', etc) data types and especially to move into templates (although absolutely NOT the Hewlett Packard template library!). Given my current understanding of inheritance in particular it seems to me that using pre-initialized data members rather than Constructor-initialization makes object derivation even more complicated, not less so.

What do you chaps think? Do you still use Constructors to initialize your data members or have you shifted over to the new style of working? If so, do you find it easier? Does it make the 'thinking ahead' that is required for working with inheritance and polymorphism more tricky for you?

are you talking about initialisation of static member variables?
Last edited on
Not specifically, but I believe you can also initialize static data members in this same new way.
Constructors for me, too.
Helps splitting implementation details (private stuff) from end-users.
Maybe I'd do that for PODs.
THAT is a really good point EssGeEich! I had not though of it from the data-hiding perspective.

In that case do you use the 'mem-list':

1
2
3
4
ExampleClass::ExampleClass():iSize(1):iBufferLength(255)
{

}


...style in your constructor or do you write explicit:

1
2
3
4
5
ExampleClass::ExampleClass()
{
    iSize=1;
    iBufferLength=255;
}


...constructors?
Initialization list (the first, you also got it slightly wrong, it looks like: Class::Class(int a, char b) : c(a), d(b), e(new char[a]) {} ).
I'm a fan of one-liner functions, and init lists are my heaven.
Ahh... In THAT case you are setting your data-members by values that come in through a non-default constructor. Can you also set them to be constants using the same format? I am not being awkward - I genuinely don't know!

As a follow up, do you run in to readability problems if you are using a mem-list style and have many data-members to initialize? I ask because I was about to redo my class in initilizer list style, but then thought about how long the line of initializers would be! I suppose there is a lesson to not have an unmanageably long list of datamembers!!!

UPDATE: ...and YES it seems you can use a mem-list to assign constants as well as variables that come from constructor parameters. This means you can use the mem-list on the default constructor also.
Last edited on
Yes, you can.
Anyways for many members, I set one or two each line.
Remember the initialization list's order does not matter: the members' constructions happen in declaration order.
Though, for readability purposes, you should really put the initialization list in order of declaration, otherwise you could get confusing errors if (for example) one member uses another member in it's construction.
strictly speaking something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
...
int m_a;
int m_b;

...

Wibble::Wibble(int a, int b) 
{
   m_a = a;
   m_b = b;

}


is not initialisation. it's still assignment. better to use initialisation lists.
(Scott Meyers item 4 i think)
Hi,

Also, just to clarify, one should call all the base class constructors (in order) from the derived class initialisation list as well. This is to avoid "object slicing".

Not completely sure on the following - might need someone to clarify this: If any of the initialisation from the initialisation list throws an exception, then the C++ standard guarantees that the object will be cleaned up (properly destructed?) so we aren't left with an invalid object. I think this is because the initialisation happens before the object is deemed to have been created. To this end, one should have a try block in the initialisation list as well (for non POD variables). Google to see how to do that.

Scott Meyers also mentioned the importance of initialising all the member variables in the initialisation lists. Obviously you need to do this for all of your constructors - you probably have more than 1 per class.

I do my IL 1 variable per line with indenting, like this with mutexe 's example:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Wibble {

private:  

int m_a;
int m_b;


Wibble(int a, int b) :  // intialisation list

   m_a(a),
   m_b(b); {}  // no code in the body so I made it inline

};


That way, if you have 40 of them - it's still readable.

Regards
Excellent suggestions here guys - this is aexactly the practical advice I was hoping to recieve!!! MANY thanks indeed!

I will also check out this Scott Myers dude. I have previously been a great follower of Schildt, but recently have learned there are many who do not have a good opinion of him. Another author who's word I can trust would be very useful indeed - maybe Myers is that guy.
Have a gander at Herb Sutter as well.
I will certainly look for Herb Sutter also - I may even already have something by him that I have not got around to opening; the name sounds familiar.

As an aside, considering books - have any of you guys heard of 'Bartosz Milewski'? VERY sadly he only seemed to write one book called 'C++ in Action' that I have ever been able to find and in intention it is EXCELLENT. Sadly I am pretty sure English is the author's second language - and lets just say he speaks English a DAMN SIGHT better than I do Polish!!! - but there are some areas where it perhaps gets a little hard to follow. Also I am certain the typesetter messed up at various points because whole lines of example code are either missing or use variable names and notation that don't correspond to the rest of the example. Nonetheless it is the only book I have ever found that covers exactly the area I want to study - that is using C++ without class libraries or CLR extensions to program for Windows. Specifically, an aproach that is NOT just slightly tarted-up C style coding but instead all the OO features of C++ applied to Win32 from the ground up. I have NEVER found another book that attempts this, which is ridiculous in itself. If its windows programming its always MFC, or more recently .NET and the euphemism of 'Managed Code'.

Have any of you chaps ever turned up a title which covers the same ground?

And, Keskiverto it is cool you mention that blog article - I have read and bookmarked that very one myself!!! A really good piece that covers precisely this area in a very approachable manner.

I am also going to look in to that distinction between 'Initialization' and 'Assignment'.
keskiverto, that's a great little link. Cheers.
Registered users can post here. Sign in or register to post.