Iinitialisation via default constructor semantics

V

Victor Bazarov

Ioannis said:
[...]
Consider the code:



#include <iostream>

class Blah
{
int i;

public:

Blah(const Blah &obj) { std::cout<<"Copy Constructor called!\n";
i=obj.i; }
Blah() { std::cout<<"Default Constructor called!\n"; i=0; }
};

int main()
{
Blah poo(Blah());

}



No message is displayed here.

Because it's a declaration of a function.
 
J

JKop

Ioannis Vranos posted:
I think that some compiler optimisations take place and confuse us(??).


Consider the code:



#include <iostream>

class Blah
{
int i;

public:

Blah(const Blah &obj) { std::cout<<"Copy Constructor called!\n";
i=obj.i; }
Blah() { std::cout<<"Default Constructor called!\n"; i= 0; }
};

int main()
{
Blah poo(Blah());

}



No message is displayed here.


Well we were expecting that anyway, that the copy
constructor would be elided.

But... what I wasn't expecting was that it didn't even need
to have a public copy constructor! This shows that:

Blah poo( Blah() );

never uses a copy constructor and that it's not an
optimization at all.

In contrast to:

Blah poo = Blah();

In this case, while the copy constructor may *not* be
called, ie. it may be optimized away, still the copy
constructor must be public.


-JKop
 
O

Old Wolf

Actually it isn't. The first one (conceptually) creates a temporary
and copies it. However in almost all cases the compiler won't
bother to generate code for that because it is explicitly permitted
by the standard to just generate the object SomeStruct() and
call it 'obj' .
To do:
Blah poo = Blah();

you need a public copy constructor, while with:

Blah poo( Blah() );

you don't!
True...

class Blah
{
private:
Blah(Blah const &original) {}
public:
std::string p;
};

int main()
{
//Blah poo = Blah();
Blah poo ( Blah() );

Try this:
poo.p = "whoopsie";
I think even a non-'shit' compiler would have trouble with 'poo.p'

Moral of the story: just because something compiles, doesn't
mean that it did what you expected.
}

And all along I though the two were identical!

Alas no.
BTW, have you considered:
Blah foo();
?
Remember how you can't copy an "std::eek:stringstream"...
int main()
{
std::eek:stringstream poo( std::eek:stringstream() );
}
It's just so beautiful... :-D

Yes but you can't actually define this function with a return
statement (as discussed in a previous thread) so you won't
be able to call it without generating UB.
 
I

Ioannis Vranos

Old said:
Actually it isn't. The first one (conceptually) creates a temporary
and copies it. However in almost all cases the compiler won't
bother to generate code for that because it is explicitly permitted
by the standard to just generate the object SomeStruct() and
call it 'obj' .


No. SomeStruct was a POD and its members are initialised to 0.
 
V

Victor Bazarov

Ioannis said:
No. SomeStruct was a POD and its members are initialised to 0.

You should re-think the number of times you say "no" in this NG. If
'SomeStruct' is a POD, SomeStruct() does initialise its members to 0,
so "Old Wolf" is correct saying that SomeStruct() is "generated". Now,
the statement

T a = b;

is called _copy-initialisation_ in the Standard, and that means that
_semantically_ it does create a temporary and then initialise 'a' with
it. Also, as "Old Wolf" says, the compiler is permitted to initialise
'obj' directly instead of creating the temporary.

So, why did you say "no"?

V
 
I

Ioannis Vranos

Victor said:
You should re-think the number of times you say "no" in this NG. If
'SomeStruct' is a POD, SomeStruct() does initialise its members to 0,
so "Old Wolf" is correct saying that SomeStruct() is "generated". Now,
the statement

T a = b;

is called _copy-initialisation_ in the Standard, and that means that
_semantically_ it does create a temporary and then initialise 'a' with
it. Also, as "Old Wolf" says, the compiler is permitted to initialise
'obj' directly instead of creating the temporary.

So, why did you say "no"?


So what you are saying essentially, is that a SomeStruct temporary is
created with all its members initialised to 0, and then it is copied
with the copy-constructor to the one on the left.


However that would imply that T a; alone would have the same effect.

What I know is that T a= T(); is a special syntax for POD types that
provides an initialisation to 0 and that no temporary is created.
 
V

Victor Bazarov

Ioannis said:
So what you are saying essentially, is that a SomeStruct temporary is
created with all its members initialised to 0, and then it is copied
with the copy-constructor to the one on the left.

Yes. That's how the standard specifies it. I didn't make it up. Do
get a copy of the Standard and read about object construction and
initialisation.
However that would imply that T a; alone would have the same effect.

How so?

Read the archives (and the Standard) about the difference between

T *a = new T;
and
T *a = new T();

for POD. Perhaps it will become a bit clearer for you.
What I know is that T a= T(); is a special syntax for POD types that
provides an initialisation to 0 and that no temporary is created.

What you know is wrong. Read 8.5/14. Nowhere in that paragraph does
the Standard say anything specific to POD for copy-initialisation. Your
knowledge apparently is about a _possible_ short-cut the compiler is
allowed to take based on 12.8/15.

V
 
I

Ioannis Vranos

Victor said:
What you know is wrong. Read 8.5/14. Nowhere in that paragraph does
the Standard say anything specific to POD for copy-initialisation. Your
knowledge apparently is about a _possible_ short-cut the compiler is
allowed to take based on 12.8/15.


8.5//5 says:

"To value-initialize an object of type T means:

— if T is a class type (clause 9) with a user-declared constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default constructor);

— if T is a non-union class type without a user-declared constructor,
then every non-static data member and base-class component of T is
value-initialized;

— if T is an array type, then each element is value-initialized;

— otherwise, the object is zero-initialized"



8.5//7:

"An object whose initializer is an empty set of parentheses, i.e., (),
shall be value-initialized."


That means that a POD:

T x = T();


is "zero-initialized".


Zero-initialized doesn't mean a temporary is created and copied with the
copy constructor. but initialised to 0 directly.
 
R

Ron Natalie

Ioannis Vranos said:
"An object whose initializer is an empty set of parentheses, i.e., (),
shall be value-initialized."


That means that a POD:

T x = T();


is "zero-initialized".


Zero-initialized doesn't mean a temporary is created and copied with the
copy constructor. but initialised to 0 directly.
In the case of the declaration:
T x = T();
The "object whose initalizer is the empty set of parentheses" is not
x. It's the temporary object on the right side of the copy initialization
syntax.

It is copy initialization REGARDLESS of whether T is POD or not.
 

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,774
Messages
2,569,598
Members
45,146
Latest member
Vinay KumarNevatia_
Top