Iinitialisation via default constructor semantics

I

Ioannis Vranos

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?
 
R

Ron Natalie

Ioannis Vranos said:
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.
 
I

Ioannis Vranos

Ron said:
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.
 
A

Andrew Koenig

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

Ioannis Vranos

Andrew said:
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?
 
J

JKop

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
 
J

JKop

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
 
A

Andrew Koenig

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

Ioannis Vranos

Andrew said:
It applies to every member of built-in type of any class that has no
explicitly defined constructors.


Interesting. Thanks for the info!
 
I

Ioannis Vranos

JKop said:
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.
 
I

Ioannis Vranos

JKop said:
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.
 
A

Andrew Koenig

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

Ioannis Vranos

Andrew said:
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.
 
A

Andrew Koenig

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

Ioannis Vranos

Andrew said:
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"?
 
I

Ioannis Vranos

JKop said:
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.
 
J

JKop

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
 
J

JKop

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
 
J

JKop

Remember how you can't copy an "std::eek:stringstream"...


#include <string>
#include <sstream>

int main()
{
std::eek:stringstream poo( std::eek:stringstream() );
}


It's just so beautiful... :-D


-JKop
 
I

Ioannis Vranos

JKop said:
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.
 

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,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top