View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Is that way of using constructor really better ?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

29 replies to this topic

### #1Agbahlok  Members

Posted 03 October 2012 - 06:08 PM

Hello.
Not so long ago I started to learn D3D11 and at the moment I'm swimming through "Beginning DirectX 11 Game Programming" book. I found one thing, which I'm curious about. Author said that constructor’s member initialize list can be more efficient and is better programming practice than letting a constructor do the job in default way.

My question is as in topic, is that way of initializing members really better ?

Example from book:

D3DBase::D3DBase() : driverType_( D3D_DRIVER_TYPE_NULL ), featureLevel_( D3D_FEATURE_LEVEL_11_0 ),
d3dDevice_( 0 ), d3dContext_( 0 ), swapChain_( 0 ), backBufferTarget_( 0 )

Thank you in advance for any help.

Edited by Agbahlok, 03 October 2012 - 06:09 PM.

### #2Bregma  Members

Posted 03 October 2012 - 06:48 PM

POPULAR

Yes.

Constructing your members with initial values is always as good as or better than constructing your members with default values and then assigning them an "initial" value later.

Why?

(1) it's often less work (cpu cycles, memory)
(2) it's often less code... the most efficient code is code you don't write
(3) your invariants are never ever violated (the object is never in an invalid state)
(4) some kinds of members, eg. references, must be initialized using an initializer list, so just do them all that way for consistency

There are some coding standards, such as the famous Google guidelines, that discourage you from initializing member variables using initializer lists. Such standards generally forbid the use of other features introduced into the language in the early 1990s and were obviously written either by a summer student or someone trying hard to sabotage the use of C++ in their organization to the benefit of their own religious language fervour. You should aim not to be one of those people.
Stephen M. Webb
Professional Free Software Developer

### #3Servant of the Lord  Members

Posted 03 October 2012 - 08:59 PM

POPULAR

Not just references, but also inherited classes must be constructed in initializer lists:
SubClass::SubClass(int blah) : BaseClass(blah) { }

With C++11 you can use "constructor delegating" (to call one constructor from another constructor) - this must also be done by initializer lists:
class MyClass()
{
public:
MyClass() : MyClass("Unnamed", 5ft + 9in, BrownColor, 160lbs) {}
MyClass(std::string name, Color eyeColor) : MyClass(name, 5ft + 9in, eyeColor, 160 lbs)  {}
MyClass(std::string name, int height, int weight) : MyClass(name, height, BrownColor, weight) {}
MyClass(std::string name, int height, Color eyeColor, int weight) : name(name), height(height), eyeColor(eyeColor), weight(weight) {}
}
The above is C++11 specific code.

How-so ever! Also in C++11, you get 'Non-static data member initializers'. *squeals with joy*

This will allow you to do this instead:
class MyClass()
{
public:
MyClass() :  {}
MyClass(std::string name, Color eyeColor) : name(name), eyeColor(eyeColor)  {}
MyClass(std::string name, int height, int weight) : name(name), height(height), weight(weight) {}
MyClass(std::string name, int height, Color eyeColor, int weight) : name(name), height(height), eyeColor(eyeColor), weight(weight) {}

private:
std::string name = "Unnamed"; //I get to do default initialization right in the class body! Sweet!
int height = 5ft + 9in;
int weight = 160lbs;
Color eyeColor = BrownColor;
}

Edited by Servant of the Lord, 03 October 2012 - 09:00 PM.

It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #4Cornstalks  Members

Posted 03 October 2012 - 11:24 PM

[edit: I was waaaay off on my original comment]

@Servant of the Lord: you should prefix literals with an underscore, as literal suffixes not starting with an underscore are reserved for future use. But thanks for reminding me that they exist!

Edited by Cornstalks, 04 October 2012 - 12:43 AM.

[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

### #5Ryan_001  Prime Members

Posted 04 October 2012 - 04:51 AM

Most modern compilers will optimize the trivial stuff. So I only stick important things (large items, parent classes, references, ect...) in the initializer list, as I really don't like them. My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.

### #6mrbastard  Members

Posted 04 October 2012 - 05:23 AM

My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.

Ah, but should initialisation be in the initialiser list order, or the order you declared them in the class declaration?

FWIW many coding standards suggest keeping your initialiser lists in the same order as your member declarations for exactly this reason.

### #7Ryan_001  Prime Members

Posted 04 October 2012 - 05:41 AM

My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.

Ah, but should initialisation be in the initialiser list order, or the order you declared them in the class declaration?

FWIW many coding standards suggest keeping your initialiser lists in the same order as your member declarations for exactly this reason.

Their order in the class definition is either for readability/clarity, or compactness/cache coherency. No one orders their variables in intialization order, at least, no one outside of C++. Not to mention dependencies can change based on the constructor that is chosen. If the order of initialization occurs in order of the intialization list, then at least you have some control in regards to dependencies. Course IMO the best solution is just to use intializtion lists when absolutely necessary, use standard C++ code the rest of the time.

Posted 04 October 2012 - 05:46 AM

POPULAR

use intializtion lists when absolutely necessary, use standard C++ code the rest of the time.

The initializer lists are standard C++ code.

### #9Bregma  Members

Posted 04 October 2012 - 07:20 AM

POPULAR

My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.

Ah, but should initialisation be in the initialiser list order, or the order you declared them in the class declaration?

FWIW many coding standards suggest keeping your initialiser lists in the same order as your member declarations for exactly this reason.

That, and because the language standard clearly and unambiguously specifies that member data is initialized in the order of declaration regardless of the order in which they appear in initializer lists. If there is a compiler that does not issue a warning when you put initializers out of order, you should switch to one that does. If you ignore the warnings the compiler gives you, blame only yourself.

If your coding standards suggest you write bad code, consider dropping that standard.

Consider also that if other people have to maintain your code, and they have become used to good practices such as initializing all member data in initializer lists, then you increase the maintenance cost of your software.
Stephen M. Webb
Professional Free Software Developer

### #10clb  Members

Posted 04 October 2012 - 08:22 AM

One gotcha though related to initializer lists is that exception safety is not possible if allocating memory to raw pointers.

Consider
Bar::Bar()
{
throw SomeException();
}

class Foo
{
int *somePointer;
Bar bar;
};

Foo::Foo()
:somePointer(new int[10])
{
}

Foo::~Foo()
{
delete[] somePointer;
}


The above code has a memory leak, somePointer is never freed since construction of Bar throws an exception.

Edited by clb, 04 October 2012 - 08:22 AM.

Me+PC=clb.demon.fi | C++ Math and Geometry library: MathGeoLib, test it live! | C++ Game Networking: kNet | 2D Bin Packing: RectangleBinPack | Use gcc/clang/emcc from VS: vs-tool | Resume+Portfolio | gfxapi, test it live!

### #11SiCrane  Moderators

Posted 04 October 2012 - 08:38 AM

POPULAR

No, it's possible to handle that case, it's just ugly, annoying and doesn't scale well.
Foo::Foo()
try : somePointer(new int[10])
{
// constructor body
} catch (SomeException & s) {
delete [] somePointer;
throw;
}


### #12Bregma  Members

Posted 04 October 2012 - 09:52 AM

POPULAR

One gotcha though related to initializer lists is that exception safety is not possible if allocating memory to raw pointers.

....

The above code has a memory leak, somePointer is never freed since construction of Bar throws an exception.

It's true that you can write bad code in any language. In this case, the language is C.

The C++ answer to that is do not use C-style raw pointers.
Bar::Bar()
{
throw SomeException();
}

class Foo
{
std::unique_ptr<int[]> somePointer;
Bar bar;
};

Foo::Foo()
:somePointer(new int[10])
{
}

Foo::~Foo()
{
}

Wow, less code, exception safe.

Of course, there's the response "but I prefer to write bad code and bad code doesn't work, therefore C++ is bad", but all that kind of argument does for me is make me respect you less.
Stephen M. Webb
Professional Free Software Developer

### #13Servant of the Lord  Members

Posted 04 October 2012 - 10:50 AM

POPULAR

The C++ answer to that is do not use C-style raw pointers.

QFT.

Of course, there's the response "but I prefer to write bad code and bad code doesn't work, therefore C++ is bad"

"I get my hands dirty when I try to garden without a shovel!"
Then use a shovel! It's sitting two feet away from you...
"C++ is bad, because it lets you dig with your hands if you want to. *My* language glues the shovel to your hands."

C++ isn't intended to, nor designed for, protecting users from themselves.
Now excuse me while I go try to make a pot of coffee with a shovel still glued to my hands.
It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #14mrbastard  Members

Posted 04 October 2012 - 12:18 PM

If there is a compiler that does not issue a warning when you put initializers out of order, you should switch to one that does.

FYI Visual c++ 2012 does not issue a warning about this with /wall (and 'language extensions' disabled fwiw). I know gcc does, and I agree that it's a useful warning.

### #15tanzanite7  Members

Posted 04 October 2012 - 02:52 PM

	 int height = 5ft + 9in;
int weight = 160lbs;


O_o, units!? That would be absolutely awesome. Is this some c++11 thing? How does that work? Ref? (Google gave nothing)

### #16Cornstalks  Members

Posted 04 October 2012 - 02:54 PM

	 int height = 5ft + 9in;
int weight = 160lbs;


O_o, units!? That would be absolutely awesome. Is this some c++11 thing? How does that work? Ref? (Google gave nothing)

They are user-defined literals. Note that they should be prefixed with an underscore to be technically right. You have to declare and define the custom literals yourself.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

### #17Servant of the Lord  Members

Posted 04 October 2012 - 03:18 PM

Yep, they are a C++11 feature. Suffixes only, no prefixes at this point. Here's wikipedia's thoughts.
Alas I can't use it yet, since I'm still on MinGW/GCC 4.6, and those (and most of the above C++11 features I mentioned) are on 4.7.

@Cornstalks: Thanks for the tips about the underscore! The user-defined literals should've also (better/safer coding) returned a user-defined type, like Length, instead of putting it into a generic int: Length myHeight = (4_feet + 8_inches);

Edited by Servant of the Lord, 04 October 2012 - 03:27 PM.

It's perfectly fine to abbreviate my username to 'Servant' or 'SotL' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

### #18Agbahlok  Members

Posted 04 October 2012 - 03:27 PM

Thanks a lot for all those MUCH useful answers ! I didn't even expect to learn so much when I posted this thread. I know everything I wanted to know and even more. Well, I gave most of you +rep. Also you convinced me to use initializer lists more often. It's just drop in the ocean of knowledge I'd like to have, but, well, that's a step. Thank you.

### #19Slavik81  Members

Posted 04 October 2012 - 04:33 PM

If there is a compiler that does not issue a warning when you put initializers out of order, you should switch to one that does.

FYI Visual c++ 2012 does not issue a warning about this with /wall (and 'language extensions' disabled fwiw). I know gcc does, and I agree that it's a useful warning.

Yeah, msvc is the only compiler I know of that doesn't support that warning. For gcc, clang and intel, the flag is -Wreorder.

You could vote for it if you want Microsoft to add it.

### #20taz0010  Members

Posted 05 October 2012 - 11:40 PM

Most modern compilers will optimize the trivial stuff. So I only stick important things (large items, parent classes, references, ect...) in the initializer list, as I really don't like them. My big issue is that the order items are initlialized in the initializer list is not the same order as they are listed. Which for dependent items can really lead to some hard to track down bugs.

Why is this being voted down? His gripe about the initialiser list order not being the actual initialisation order is perfectly valid. It's intuitive to assume that the variables are going to be initialised in the order that the initialisation code is written - which is exactly the case whenever you initialise something using the equals sign.

Also mentioned in this topic, ordering your members for alignment or caching reasons can potentially break your code if one member was initialised using the value of another. And since headers are used, the potential error will not even be visible in the file where the initialisation code is actually written.

Personally if I have primitive variables that I need to initialise in a specific order, I'm not going to rely on the class definition order to do it, and that means good old fashioned assignment with the = operator.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.