Initialization lists and optimization

M

Marcin Kalicinski

Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?

Best regards,
Marcin
 
J

JKop

Marcin Kalicinski posted:
Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?

Best regards,
Marcin


Not of which I am aware. I believe the sole reason that we have the first
form is for the initialization of const objects and references, eg.

struct S
{
const int x;
S(int y) : x(y) { } //1
S(int y) { x = y } //2 Compile ERROR
};


As for one being more efficient than the other, I can't think of any reason
off the top of my head.


-JKop
 
J

Jeff Flinn

JKop said:
Marcin Kalicinski posted:
Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?
[snip]

As for one being more efficient than the other, I can't think of any reason
off the top of my head.

Writing:

S::S( int y ){ x = y; }

Actually is processed as:

S::S( int y ):x(){ x = y; }

So you are default(or is it value) initializing, then assigning a value.
Which is less efficient than:

S::S( int y ):x(y){}

Jeff F
 
T

Tao Bo

Marcin Kalicinski said:
Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?

Best regards,
Marcin

I think it's nothing about optimization, but the tow constructor have
different behavior when construct an object. For constructor 1, the x will
be initialized before enter

constructor, for a statement like

S ps = new S(1);

the compiler will generate code like

ps = operater new (sizeof(S)); // Allocate
memory

ps->x = 1;

ps->S(1);



The difference between the two constructor will be very subtle when you
construct some more complex object witch in turn contain other objects or
you want to make your

constructor "exception free". The book "Exceptional C++" gives many deep
discussion of these two kind of construcors.





Tao Bo
 
M

Mike Wahler

Marcin Kalicinski said:
Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?

The compiler may apply any optimizations at all, as
long as the 'as if' rule is observed.

But note that // 1 and // 2 above express different things.
The former initializes the member 'x', the latter does not,
but assigns 'x' a value after it is created.

This can make a difference:

S(int y) : x(y)
{
int i = x; /* OK, 'x' has a value */
}

S(int y)
{
/* suppose we forget to assign 'x' a value */

int i = x; /* OOPS, undefined behavior */
}

Also the intitialization-list form is required for certain
things, such as initialization of const or reference members,
or base class portions of objects.


-Mike
 
M

Mike Wahler

Jeff Flinn said:
JKop said:
Marcin Kalicinski posted:
Hi all,

struct S
{
int x;
S(int y): x(y) { } // 1
S(int y) { x = y; } // 2
}

Is there any difference between 1 and 2 regarding code optimizations that
the compiler may apply?
[snip]

As for one being more efficient than the other, I can't think of any reason
off the top of my head.

Writing:

S::S( int y ){ x = y; }

Actually is processed as:

S::S( int y ):x(){ x = y; }

No. (well a compiler is not disallowed from doing
it that way, but it's not required).

'x' is not necessarily initialized prior to entering
the constructor body. The only time that would be
guaranteed to happen is if 'x' were of a user-defined
type with a default constructor (type 'int' is not).
So you are default(or is it value) initializing, then assigning a value.
Which is less efficient than:

S::S( int y ):x(y){}

The efficiency of one form over another is implementation-dependent.

-Mike
 
S

Siemel Naran

Jeff Flinn said:
Writing:

S::S( int y ){ x = y; }

Actually is processed as:

S::S( int y ):x(){ x = y; }

So you are default(or is it value) initializing, then assigning a value.
Which is less efficient than:

S::S( int y ):x(y){}

Not true. In the first initialization, the system does call the default
constructor for user defined types like std::string, and thus it is only
less efficient when your class holds a std::string or other user type. But
for fundamental types like int, the system does not call the default
constructor, and thus it does not call the default constructor for x. Thus
both methods are equivalent, and compilers typically handle both ways
exactly the same. This rule is present for historical reasons. Exception:
if the instance of the object you declare is at static or global scope, then
the system does call the default constructor of fundamental types (but it
does not for an S object declared as a local variable).
 
S

Siemel Naran

Mike Wahler said:
No. (well a compiler is not disallowed from doing
it that way, but it's not required).

For user types, class x may not even have a default constructor, so in
general the compiler cannot do it this way.
'x' is not necessarily initialized prior to entering
the constructor body. The only time that would be
guaranteed to happen is if 'x' were of a user-defined
type with a default constructor (type 'int' is not).

Not exactly true on "if 'x' were of a user-defined type with a default
constructor ". 'x' may be a user defined type without a default
constructor, or any constructors, but it contains objects that have a
default constructor, so in that case there is a compiler generated default
constructor that calls the default constructor of the contained objects.

struct X {
std::string s;
};

S::S(const X& x2) { x = x2; }
// above inefficient: same as
S::S(const X& x2) : x() { x = x2; }
// which is practically same as (though the syntax is illegal in C++)
S::S(const X& x2) : x.s() { x = x2; }

Also, if you declare your class S at global or static scope you get zero
initialization, even if 'x' is a fundamental type. Also a strange rule for
historical reasons.
 
M

Mike Wahler

Siemel Naran said:
For user types, class x may not even have a default constructor, so in
general the compiler cannot do it this way.


Not exactly true on "if 'x' were of a user-defined type with a default
constructor ". 'x' may be a user defined type without a default
constructor, or any constructors, but it contains objects that have a
default constructor, so in that case there is a compiler generated default
constructor that calls the default constructor of the contained objects.

Right. My reply was incomplete. Thanks for the elaboration.
struct X {
std::string s;
};

S::S(const X& x2) { x = x2; }
// above inefficient: same as
S::S(const X& x2) : x() { x = x2; }
// which is practically same as (though the syntax is illegal in C++)
S::S(const X& x2) : x.s() { x = x2; }

Also, if you declare your class S at global or static scope you get zero
initialization, even if 'x' is a fundamental type. Also a strange rule for
historical reasons.

Also correct. Since OP didn't give context about that, I suppose I
should have addressed the 'static vs 'automatic' issue.

-Mike
 
S

Stephen M. Webb

JKop said:
struct S
{
const int x;
S(int y) : x(y) { } //1
S(int y) { x = y } //2 Compile ERROR
};


As for one being more efficient than the other, I can't think of any reason
off the top of my head.

The second form default-constructs the member 'x' and then calls its
assignment operator to copy the value of 'y' into 'x'.

If the default constructor or assignment operator of 'x' were to be a
heavy-duty operation with side effects, say, allocating memory from
the free store, you would notice a difference.


Prefer initialization over the default-constructor-and-assignment
route where possible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top