Reputation: 4761
I have asked this question. My question now is how this works? To elaborate, how can I point to an object that is not yet initialised. I have made this MWE and it shows that the object is copy created not copy assigned .i.e. the object is not yet initialised yet I am able to point to it.
#include <iostream>
class Foo {
public:
int x;
Foo(const Foo& ori_foo) {
std::cout << "constructor" << std::endl;
x = ori_foo.x;
}
Foo& operator = (const Foo& ori_foo) {
std::cout << "operator =" << std::endl;
x = ori_foo.x;
return *this;
}
Foo(int new_x) {
x = new_x;
}
};
class BarParent {
public:
Foo *p_foo;
BarParent(Foo* new_p_foo) : p_foo(new_p_foo)
{
std::cout << (*new_p_foo).x << std::endl;
}
};
class BarChild : public BarParent {
public:
Foo foo;
BarChild(Foo new_foo)
:BarParent(&foo) //pointer to member not yet initialised
,foo(new_foo) // order of initilization POINT OF INTEREST
{}
};
int main() {
Foo foo(101);
BarChild bar(foo);
std::cout << bar.p_foo->x << std::endl;
std::cout << bar.foo.x << std::endl;
}
Output:
constructor
0
constructor
101
101
Do not be afraid of getting into details of how the memory is handled. And, where every member resides.
Upvotes: 2
Views: 427
Reputation: 1998
Don't mistake Initialization for Allocation. BarChild::foo will be allocated before the constructor is called since it is stored in place, so there will be a well defined location for BarParent::p_foo to point at. Foo's constructor will Initialize BarChild::foo, but as long as you don't try to read from BarChild::foo before the constructor is called you will not notice the ordering.
Upvotes: 5
Reputation: 171263
At this line
BarChild bar(foo);
the compiler reserves enough stack space for a BarChild
object then calls the constructor to begin the object's lifetime. Within the object the foo
member has a fixed offset, every BarChild
object has a foo
member at the same offset within it, so since the this
pointer has a known address within the constructor (it's the address of bar
on the stack) then this->foo
is also at a known address, even if the memory at that address hasn't been initialized yet. The BarChild
obejct doesn't "grow bigger" as each member is initialized, its size is fixed and space for all the members is already "reserved" before they're initialized.
This is somewhat analogous to:
char raw_memory[sizeof(Foo)]; // define block of uninitialized memory
char* addr = raw_memory; // take address of uninitialized memory
new (raw_memory) Foo; // initialize memory
The object doesn't exist yet, and it's not valid to use it, but its address is known in advance of it being initialized.
Upvotes: 3