By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,538 Members | 869 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,538 IT Pros & Developers. It's quick & easy.

Iinitialisation via default constructor semantics

P: n/a
I was confused from another thread about this:

Does this kind of initialisation
int x= int();

initialise to 0 of the type only for built in types or for *all* POD types?

That is:

struct whatever
{
int x,y;
}a=whatever();
is guaranteed a.x and a.y to be initialised to 0?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #1
Share this Question
Share on Google+
29 Replies


P: n/a

"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message news:ci**********@ulysses.noc.ntua.gr...
initialise to 0 of the type only for built in types or for *all* POD types?

T x = T();

copy initializes x with a Default-Initialized object regardless of what the type T is,
builtin, POD, or otherwise.

Jul 22 '05 #2

P: n/a
Ron Natalie wrote:
"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message news:ci**********@ulysses.noc.ntua.gr...

initialise to 0 of the type only for built in types or for *all* POD types?


T x = T();

copy initializes x with a Default-Initialized object regardless of what the type T is,
builtin, POD, or otherwise.


For built in types, this is equivalent to 0 corresponding to the type.
For non-POD types the result is the same with T x(T());
For POD types except of built in types, is it the same case with built
in types?
TC++PL mentions built in types only, for the first kind of initialisation.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #3

P: n/a
"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:ci**********@ulysses.noc.ntua.gr...
Does this kind of initialisation int x= int(); initialise to 0 of the type only for built in types or for *all* POD
types?


All POD types.

Moreover, in C++2003 (but not C++1998), it works for POD members of non-POD
structures, provided that they have no explicitly defined constructors.

Example:

struct Foo {
int x;
std::string s;
};

struct Bar {
int x;
std::string s;
Bar() { }
};

In C++1998, Foo().x is undefined; in C++ 2003, it's 0.

In both C++1998 and C++2003, Bar().x is undefined. The reason is that the
author of Bar had the opportunity to initialize x and chose not to do so,
whereas the author of Foo did not have the opportunity to initialize x,
having defined no constructor that would have provided such an opportunity.
Jul 22 '05 #4

P: n/a
Andrew Koenig wrote:
All POD types.

Moreover, in C++2003 (but not C++1998), it works for POD members of non-POD
structures, provided that they have no explicitly defined constructors.

Example:

struct Foo {
int x;
std::string s;
};

struct Bar {
int x;
std::string s;
Bar() { }
};

In C++1998, Foo().x is undefined; in C++ 2003, it's 0.

In both C++1998 and C++2003, Bar().x is undefined. The reason is that the
author of Bar had the opportunity to initialize x and chose not to do so,
whereas the author of Foo did not have the opportunity to initialize x,
having defined no constructor that would have provided such an opportunity.

Does the latest apply for POD members of non-POD structs only, or also
for POD members of classes?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #5

P: n/a
> Does the latest apply for POD members of non-POD structs only, or also
for POD members of classes?


Hmm...

#include <iostream>

class Blah
{
private:

int k; //private member makes it no longer a POD

public:

std::string j; //a non-POD member
};

int main()
{
Blah poo = Blah();
}
Blah is not a POD, *but* it hasn't got a constructor defined. I honestly
haven't a clue if "k" gets initialized to zero in the above. My guess would
be that it *isn't* initialized, based upon the premise that once it's no
longer a POD, the programmer has full control over the class, including
whether or not its member variables get default initialized... but that's
just speculation. I believe that the miranda constructor is defined as so:

Blah()
{

}
As opposed to:

Blah() : k()
{

}
This is a nice little technical conversation I must say!
-JKop
Jul 22 '05 #6

P: n/a
May I make a suggestion...

Nobody mention the obsolete 1998 Standard, it's been
replaced; just speak about the relevant 2003 Standard, that
way no-one gets confused.
-JKop
Jul 22 '05 #7

P: n/a
"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:ci**********@ulysses.noc.ntua.gr...
Does the latest apply for POD members of non-POD structs only, or also for
POD members of classes?


It applies to every member of built-in type of any class that has no
explicitly defined constructors.
Jul 22 '05 #8

P: n/a
Andrew Koenig wrote:
It applies to every member of built-in type of any class that has no
explicitly defined constructors.

Interesting. Thanks for the info!

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #9

P: n/a
JKop wrote:
Hmm...

#include <iostream>

class Blah
{
private:

int k; //private member makes it no longer a POD

public:

std::string j; //a non-POD member
};

int main()
{
Blah poo = Blah();
}
Blah is not a POD, *but* it hasn't got a constructor defined.
That is, it has the built in default constructor and copy constructor
and assignment operator.
I honestly
haven't a clue if "k" gets initialized to zero in the above. My guess would
be that it *isn't* initialized, based upon the premise that once it's no
longer a POD, the programmer has full control over the class, including
whether or not its member variables get default initialized...

But as was said, even for non-POD structs POD members get initialised to
0 upon this kind of assignment.

but that's
just speculation. I believe that the miranda constructor is defined as so:

miranda?

Blah()
{

}
As opposed to:

Blah() : k()
{

}


I can't understand what you mean, but this kind of assignment has not
anything to do with your definition above.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #10

P: n/a
JKop wrote:
May I make a suggestion...

Nobody mention the obsolete 1998 Standard, it's been
replaced; just speak about the relevant 2003 Standard, that
way no-one gets confused.

The 2003 standard is a bug-fixed version of the 1998 standard. Since it
is not a major standard revision, I guess that it will continue to be
mentioned as C++98 around, as has been the case of C90 and C99 and their
own fixes.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #11

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message
news:yO*******************@news.indigo.ie...
class Blah
{
private:
int k; //private member makes it no longer a POD
public:
std::string j; //a non-POD member
}; int main()
{
Blah poo = Blah();
} Blah is not a POD, *but* it hasn't got a constructor defined. I honestly
haven't a clue if "k" gets initialized to zero in the above. My guess
would
be that it *isn't* initialized, based upon the premise that once it's no
longer a POD, the programmer has full control over the class, including
whether or not its member variables get default initialized... but that's
just speculation.


The answer is that Blah().k is undefined in C++1998 and zero in C++2003.
Jul 22 '05 #12

P: n/a
Andrew Koenig wrote:
The answer is that Blah().k is undefined in C++1998 and zero in C++2003.


However this is true only when we do Blah poo=Blah(); and not in the
case of Blah poo;
However this is tricky, and notionally speaking inconsistent. That's why
I think that probably in the next revision of the standard all POD types
if not initialised with a value, to be initialised to 0 in their type.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #13

P: n/a
"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:ci***********@ulysses.noc.ntua.gr...
The answer is that Blah().k is undefined in C++1998 and zero in C++2003.
However this is true only when we do Blah poo=Blah(); and not in the case
of Blah poo;
Correct.
However this is tricky, and notionally speaking inconsistent. That's why I
think that probably in the next revision of the standard all POD types if
not initialised with a value, to be initialised to 0 in their type.


We discussed this while developing C++98 and explicitly decided against it.
The issue is structures like this:

struct X{
int x[1000];
// other stutt
};

void foo()
{
X xx;
// ...
}

C specifies that the elements of xx.x are uninitialized. If C++ were to
require them to be initialized, it would put C++ at a performance
disadvantage when compared with C.
Jul 22 '05 #14

P: n/a
Andrew Koenig wrote:
We discussed this while developing C++98 and explicitly decided against it.
The issue is structures like this:

struct X{
int x[1000];
// other stutt
};

void foo()
{
X xx;
// ...
}

C specifies that the elements of xx.x are uninitialized. If C++ were to
require them to be initialized, it would put C++ at a performance
disadvantage when compared with C.

OK. Something else, in a previous message you used the notation Blah().k
.. Do you mean that the members of a *temporary* POD get initialised to
0, or was a "fast syntax"?

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #15

P: n/a
JKop wrote:
Blah is not a POD, *but* it hasn't got a constructor defined. I honestly
haven't a clue if "k" gets initialized to zero in the above. My guess would
be that it *isn't* initialized, based upon the premise that once it's no
longer a POD, the programmer has full control over the class, including
whether or not its member variables get default initialized... but that's
just speculation. I believe that the miranda constructor is defined as so:

Blah()
{

}
As opposed to:

Blah() : k()
{

}
This is a nice little technical conversation I must say!

Yes it is. By the way, I want to note that the kind of assignment in POD
types:
Blah poo=Blah();

does not create a temporary and then uses the copy constructor but is a
special syntax, equivalent to initialisation to 0 (in contrast to
non-POD types).
So int x=int(); is equivalent to int x=0;
struct SomeStruct
{
int x,y;
};
SomeStruct obj=SomeStruct(); is equivalent to

SomeStruct obj={0,0};
and not to SomeStruct obj(SomeStruct());
where a temporary is created and copied.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #16

P: n/a
> SomeStruct obj = SomeStruct(); is equivalent to

SomeStruct obj={0,0};
and not to SomeStruct obj(SomeStruct());
where a temporary is created and copied.

The exact opposite, which I am about to prove...

To do:

Blah poo = Blah();
you need a public copy constructor, while with:
Blah poo( Blah() );

you don't!
Compile the following. Note how I've commented out the first definition. If
you remove the // and recompile, it won't because there's no copy
constructor!

In summation: Blah poo( Blah() ); is what you want!
#include <iostream>

class Blah
{
private:

Blah(Blah const &original) {}

public:

int k;

wchar_t* r;

std::string p;
};

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

Blah poo ( Blah() );
}
And all along I though the two were identical!

-JKop
Jul 22 '05 #17

P: n/a
What this shows is that:

Blah poo( Blah() );
will *never* create a temp and copy it, even on a shit
compiler! I lloovvee it!
-JKop
Jul 22 '05 #18

P: n/a

Remember how you can't copy an "std::ostringstream"...
#include <string>
#include <sstream>

int main()
{
std::ostringstream poo( std::ostringstream() );
}
It's just so beautiful... :-D
-JKop

Jul 22 '05 #19

P: n/a
JKop wrote:

The exact opposite, which I am about to prove...

To do:

Blah poo = Blah();
you need a public copy constructor, while with:
Blah poo( Blah() );

you don't!
Compile the following. Note how I've commented out the first definition. If
you remove the // and recompile, it won't because there's no copy
constructor!

In summation: Blah poo( Blah() ); is what you want!
#include <iostream>

class Blah
{
private:

Blah(Blah const &original) {}

public:

int k;

wchar_t* r;

std::string p;
};

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

Blah poo ( Blah() );
}
And all along I though the two were identical!

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.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #20

P: n/a
Ioannis Vranos wrote:
[...]
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.
Jul 22 '05 #21

P: n/a
Ioannis Vranos posted:
JKop wrote:

The exact opposite, which I am about to prove...

To do:

Blah poo = Blah();
you need a public copy constructor, while with:
Blah poo( Blah() );

you don't!
Compile the following. Note how I've commented out the first definition. If you remove the // and recompile, it won't because there's no copy constructor!

In summation: Blah poo( Blah() ); is what you want!
#include <iostream>

class Blah
{
private:

Blah(Blah const &original) {}

public:

int k;

wchar_t* r;

std::string p; };

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

Blah poo ( Blah() ); }
And all along I though the two were identical!

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
Jul 22 '05 #22

P: n/a

Shame on me!
Blah poo( Blah() );
is a function declaration!
-JKop
Jul 22 '05 #23

P: n/a
JKop <NU**@NULL.NULL> wrote:
Ioannis Vranos wrote:
SomeStruct obj = SomeStruct(); is equivalent to
SomeStruct obj={0,0};

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::ostringstream"...
int main()
{
std::ostringstream poo( std::ostringstream() );
}
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.
Jul 22 '05 #24

P: n/a
Old Wolf wrote:
SomeStruct obj = SomeStruct(); is equivalent to
SomeStruct obj={0,0};

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.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #25

P: n/a
Ioannis Vranos wrote:
Old Wolf wrote:
SomeStruct obj = SomeStruct(); is equivalent to
SomeStruct obj={0,0};


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.


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
Jul 22 '05 #26

P: n/a
Victor Bazarov wrote:
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.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #27

P: n/a
Ioannis Vranos wrote:
Victor Bazarov wrote:
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.


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
Jul 22 '05 #28

P: n/a
Victor Bazarov wrote:
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.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #29

P: n/a

"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message news:cj**********@ulysses.noc.ntua.gr...

"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.

Jul 22 '05 #30

This discussion thread is closed

Replies have been disabled for this discussion.