Reputation: 81
I have this code an i am trying to understand how the compiler works:
#include <iostream>
using namespace std;
class Block
{
int data;
public:
Block(int i = 10)
: data(i)
{
cout << "I just created a Block " << endl;
}
~Block()
{
cout << "I will destroy a Block with " << data << endl;
}
void inc()
{
data++;
}
};
class A
{
Block& block1;
Block block2;
public:
A(Block& blk)
: block1(blk)
, block2(blk)
{
cout << "I just created an A " << endl;
}
A(const A& a)
: block1(a.block1)
, block2(a.block2)
{
cout << "I just created an A by copying but I will also do bad things" << endl;
block1.inc();
block2.inc();
}
~A()
{
cout << "I will destroy an A " << endl;
}
void inc()
{
block1.inc();
block2.inc();
}
};
class Fat
{
A a;
A& ra;
A* pa;
public:
Fat(A& da)
: a(da)
, ra(da)
{
pa = new A(da);
cout << "Fat just created !" << endl;
}
~Fat()
{
delete pa;
cout << "Fat to be destroyed !" << endl;
}
void inc()
{
a.inc();
ra.inc();
pa->inc();
}
};
int main()
{
Block block;
A a(block);
Fat fat(a);
fat.inc();
return 0;
}
when it creates an A object,is creating a new block or it use the existing block? why isn't running the constructor of block?
the output of the program is :
I just created a Block
I just created an A
I just created an A by copying but I will also do bad things
I just created an A by copying but I will also do bad things
Fat just created !
I will destroy an A
I will destroy a Block with 12
Fat to be destroyed !
I will destroy an A
I will destroy a Block with 12
I will destroy an A
I will destroy a Block with 11
I will destroy a Block with 15
Upvotes: 3
Views: 81
Reputation: 9735
when it creates an A object,is creating a new block or it use the existing block? why isn't running the constructor of block?
Looking at A
constructor:
A(Block& blk)
: block1(blk)
, block2(blk)
{
}
block1
is a reference to a Block
object. So it referes to the already created blk
variable, and it won't create another one. So no constructor is invoked in this case.
That is not true for block2
which is not a reference. In that case indeed a new object Block
is created, but using copy constructor.
What you've defined in your Block
class is a default constructor.
When a class instance is created starting from another object of the same class, then the copy constructor will be invoked (note: not the default constructor).
The copy constructor is implicitly defined by the compiler unless you define one yourself.
For example:
class Block {
public:
Block(const Block& other) : data(oth.data) {
std::cout << "Invoked copy 'ctor" << std::endl;
}
// ... other stuff
};
That's why your code invokes the default constructor of your class Block
only once.
Upvotes: 2
Reputation: 103733
You could have demonstrated this with much simpler code.
#include <iostream>
class Noisy
{
public:
Noisy()
{ std::cout << "Noisy default construct\n"; }
~Noisy()
{ std::cout << "Noisy destroy\n"; }
};
int main()
{
Noisy noisy1;
Noisy noisy2(noisy1);
}
Output
Noisy default construct Noisy destroy Noisy destroy
Notice that, apparently, only one object was constructed, but two were destroyed. The reason for this apparent inconsistency is because we are not logging all or our constructors. There is an implicitly generated copy constructor, which we are using to construct noisy2
in this line here:
Noisy noisy2(noisy1);
If we define the copy constructor ourselves,
#include <iostream>
class Noisy
{
public:
Noisy()
{ std::cout << "Noisy default construct\n"; }
Noisy(Noisy const&)
{ std::cout << "Noisy copy construct\n"; }
~Noisy()
{ std::cout << "Noisy destroy\n"; }
};
int main()
{
Noisy noisy1;
Noisy noisy2(noisy1);
}
Output:
Noisy default construct Noisy copy construct Noisy destroy Noisy destroy
You can see that two objects are constructed, just with different constructors. If you do this with your various classes, you should see similar results. Your references will not be logged, neither a constructor or destructor, since they are not objects.
Upvotes: 2