Reputation: 480
Consider this code:
class First
{
public:
int y;
First()
{
y = 90;
}
};
class Second{
public:
int x;
First ob; //if i comment it, value of x is initialised to zero
};
int main()
{
Second obj = Second();
cout << obj.x << endl;
}
This program gives different output when I change it:
First ob;
then value of x is initialised to zeroSecond obj;
then it has garbage value.What is the reason it behaves differently when Second class consists only built-in members and when object of another class?
And what is the difference between these statements:
Second obj = Second();
Second obj;
Upvotes: 0
Views: 182
Reputation: 361322
Case 1. When you comment out the line First ob
, then Second
class becomes a POD type, which can be value-initialized using the syntax Second obj= Second()
, and value-initialization, in case of built-in types, means zero-initialized, so x
is zero-initialized.
Case 2: When you keep the line First ob
, then Second
class becomes non-POD type, because First
class is non-POD type (as it has user-defined constructor1]). In this case, the syntax Second obj=Second()
doesn't initialize built-in data type, if you don't initialize it in the constructor.
Case 3: When write Second obj
, then there are again two cases (read them carefully):
obj
will be default constructed if there is First ob
line. And in this case, x
will not be initialized at all, as it is not manually initialized in the constructor of Second
.
obj
will not be initialized at all if you First ob
line is commented out. In this case, Second
becomes a POD, and POD types are not initialized if you only write Second obj
.
1 See this related topic:
Upvotes: 3
Reputation: 476970
At the risk of being a bit tangential, let me post a modified version of the problem, along with a discussion. Let's consider these classes:
struct Agatha
{
int x;
};
struct Claire
{
Claire() { }
int x;
};
To simplify the initialization syntax and make the example analyzable with Valgrind, let's use dynamic objects:
#include <memory>
#include <iostream>
int main()
{
std::unique_ptr<Agatha> p1(new Agatha); // #1d
std::unique_ptr<Agatha> p2(new Agatha()); // #1v
std::unique_ptr<Claire> q1(new Claire); // #2d
std::unique_ptr<Claire> q2(new Claire()); // #2v
std::cout << p1->x
<< p2->x
<< q1->x
<< q2->x
<< std::endl;
}
Only one of those printing lines is correct! Can you figure out which one?
The answer is #1v. Let's discuss:
Case #1d default-initializes an aggregate, which default-initializes each member, which default-initializes Agatha::x
, which leaves it uninitialized.
Case #1v value-initializes a aggregate, which value-initializes all members, and thus value-initializes Agatha::x
, and thus zero-initializes it. (This is the good case.)
Case #2d default-initializes a non-aggregate, which calls the default constructor. The default constructor of Claire
does not initialize Claire::x
, so it is left uninitialized.
Case #2d value-initialization of a non-aggregate also calls the default constructor, and the situation is identical to #2v.
Notice that the whole discussion has nothing to do with PODness, but merely with whether the class is an aggregate, like Agatha
, or a non-trivial class type with like Claire
. You could add a member of type std::string
to Agatha
without affecting this example.
Upvotes: 1
Reputation: 7838
Have a read through the accepted answer to Do the parentheses after the type name make a difference with new? - without the First
object, your class is an 'A', with it your class is a 'B'. Second obj;
will default-initialize it, Second obj = Second();
will value-initialize it.
This is one of the areas where C++ has some quite tricky and surprising rules, but I'm not going to cover them in detail here as they've been very well explained in the above question.
What do the following phrases mean in C++: zero-, default- and value-initialization? is also related.
Edit:
The above links only really cover the initialization side of things, not the rules on what makes a class trivial/POD/standard layout/etc. What are Aggregates and PODs and how/why are they special? covers that side of things.
Upvotes: 1