source programs in C + +:
Copy Code code as follows:
Class X {
Private
int i;
};
int main () {
x x;
}
The class X above does not have a constructor defined, just an int i.
The following is an assembler:
Copy Code code as follows:
; 7:int Main () {
Push EBP;EBP is a register that always points to the bottom of a function call stack and, as the base address, accesses the variable on the call stack with an offset, but there are no variables to access, so it doesn't work
MOV ebp, esp; these two sentences are meant to hold the value of the base address of the stack before calling main, and to point EBP to the bottom of the main call stack EBP
push ecx; ecx the value of the register to the stack, the stack top pointer esp to move forward 4byte
The function of this sentence is to reserve 4byte of space for the object to be created and write the value of ECX to it.
; 8:x X;
; 9:}
xor eax, Eax;eax is also a register, this does not work
mov esp, EBP, move top of stack pointer to position before push ecx, that frees up 4byte of space
Pop ebp; Restores the base address to the state before the main call
RET 0; function return
Through the assembly discovery, through the push ecx, the compiler will stack stack top move 4byte, and the register ECX value written, Class X contains only an int, the size of just 4byte, so this sentence can be seen as the allocation of space for object X. And then there is no call to any function to properly initialize the area. Therefore, there is no initialization action when a constructor is not explicitly defined.
Let's look at a C + + program below:
Copy Code code as follows:
Class X {
Private
int i;
int j;//Add a member variable int j
};
int main () {
x x;
}
As compared to the above, a member variable int j is added to Class X, and the class size becomes 8 bytes.
The following is the corresponding sink encoding:
Copy Code code as follows:
; 8:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 8; The top pointer of the stack moves 8byte, just equal to the size of class X
; 9:x X;
; 10:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
As seen from the sink code, the stack does leave 8byte of space, just equal to the size of Class X, and does not call any function to initialize the operation, through the sub esp,8 instruction.
So, to sum up, when a class does not explicitly define a constructor, the compiler will not have any function calls to initialize, just the space required to leave the object on the top of the stack, that is, in which case the compiler will not provide the default constructor at all.
So what does the book say about the compiler providing the default constructor?
Here's the first case where the virtual member function is inside the class:
C + + source code is as follows:
Copy Code code as follows:
Class X {
Private
int i;
int j;//Add a member variable int j
Public
Virtual ~x () {
}
};
int main () {
x x;
}
Destructors as virtual functions
The following is the assembly code for the main function:
Copy Code code as follows:
; 13:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; 12byte space reserved for object x, member variable int i,int j is 8byte, because of virtual function, so vptr pointer occupies 4byte
; 14:x X;
Lea ECX, DWORD PTR _X$[EBP]; Get the first address of the X object and deposit it in the ECX register
Call?? 0x@ @QAE @xz; This calls the constructor of X
; 15:}
Lea ECX, DWORD PTR _X$[EBP]; Get the first address of an object X
Call?? 1x@ @UAE @xz; Calling destructors
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
As you can see, the constructor for object x is called, and the compiler does synthesize the default constructor.
The following is the assembler code for the constructor:
Copy Code code as follows:
?? 0x@ @QAE @xz PROC; X::x, Comdat
; _this$ = ecx
Push EBP
MOV EBP, esp
Push ECX
mov DWORD PTR _this$[ebp], ECX;ECX registers have the first address of object X
mov eax, DWORD PTR _THIS$[EBP]; The first address of object X to register EAX
mov DWORD PTR [eax], OFFSET?? _7x@@6b@ here set the value of the vptr pointer, pointing to vtable (OFFSET??). _7x@@6b@ is to get vtable address)
And through this sentence, can also prove that the vptr pointer at the object actually address
mov eax, DWORD PTR _THIS$[EBP]
mov esp, EBP
Pop EBP
RET 0
As you can see, because of the virtual function, which involves polymorphism, the constructor initializes the Vptr pointer, but does not assign the other two variable int i,int J.
As you can see from the above, when a class contains a virtual function, the compiler does provide us with a default constructor without explicitly defining the constructor. Therefore, when a class inherits from the virtual base class, it also satisfies the above case.
Next, the second scenario, Class Y inherits from class X,x explicitly defines a default constructor (not provided by the compiler), and Class Y does not define any constructors:
First look at C + + Source:
Copy Code code as follows:
Class X {
Private
int i;
Int J;
Public
X () {//x display defined default constructor
i = 0;
j = 1;
}
};
Class Y:public x{//y inherits from X
Private
int i;
};
int main () {
Y y;
}
Class Y doesn't show any constructors defined
The following is the assembly code for the main function:
Copy Code code as follows:
; 19:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; 12byte space reserved for object Y, y self member variable int i, member variable int i int j,% of 4byte parent class
; 20:y Y;
Lea ECX, DWORD PTR _Y$[EBP]; Gets the first address of the object Y, deposited in the register ECX
Call?? 0y@ @QAE @xz; constructor for calling Object Y
; 21:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
The default constructor for the default Y object provided by the compiler is called in the main function.
The following is an assembly code for the Y-object default constructor provided by the compiler:
Copy Code code as follows:
?? 0y@ @QAE @xz PROC; Y::y, Comdat
; _this$ = ecx
Push EBP
MOV EBP, esp
Push ECX
mov DWORD PTR _THIS$[EBP], the first address of object Y in Ecx;ecx
mov ecx, DWORD PTR _THIS$[EBP]
Call?? 0x@ @QAE @xz; Call the constructor of the parent class X
mov eax, DWORD PTR _THIS$[EBP]
mov esp, EBP
Pop EBP
RET 0
?? 0y@ @QAE @xz ENDP
You can see that the constructor of the Y object also invokes the constructor of the parent class to initialize the member variable inherited from the parent class, but its own member variable is still not initialized.
The following is the constructor sink encoding for the parent class X:
Copy Code code as follows:
; 7:x () {
Push EBP
MOV EBP, esp
Push ECX
mov DWORD PTR _this$[ebp], ecx; The first address of the object Y in the ECX
; 8:i = 0;
mov eax, DWORD PTR _this$[ebp], object y first address to register EAX
mov DWORD PTR [eax], 0; initialize variable i in parent class
; 9:j = 1;
mov ecx, DWORD PTR _this$[ebp], object y first address to register ECX
mov DWORD PTR [ecx+4], 1; Initializes the variable J in the parent class, and in the memory space of object Y, 8 bits starting from the first address are used to store the member variables that inherit from the parent object, and the 4byte is used to store its own member variables
Because the parent class member variable i is stored in the first address, the memory address is moved 4byte from the first address of the object Y to find the location of the parent member variable J
; 10:}
mov eax, DWORD PTR _THIS$[EBP]
mov esp, EBP
Pop EBP
RET 0
As you can see, the member variables of the Y object that inherit from the parent class are initialized by the parent class constructor. The parent object is contained in a child object, and the this pointer, the first address of the register ECX store, is always the first address of child object Y.
What if the parent class X does not define any constructors?
The following is the C + + Source:
Copy Code code as follows:
Class X {
Private
int i;
Int J;
};
Class Y:public x{//y inherits from X
Private
int i;
};
int main () {
Y y;
}
Neither the parent class nor the subclass has any constructors.
The following is the main function sink encoding:
Copy Code code as follows:
; 16:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; Like just now, reserve 12byte for object y
; 17:y Y;
; 18:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
You can see that there is no call to any function at all in main, that is, the compiler does not provide a default constructor for child object Y.
So what if there is a constructor with parameters in the parent class, and there is no constructor in the subclass? The compiler will then give an error.
In the third case, class Y contains the member object x, the member object has a default constructor for the display definition, and Class Y does not have any constructors:
First look at C + + Source:
Copy Code code as follows:
; 16:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; Like just now, reserve 12byte for object y
; 17:y Y;
; 18:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
Class X is a member object of Class Y
The following is the assembly code for the main function:
Copy Code code as follows:
; 21:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; A variable that reserves a 12byte member object for Object Y is a 8byte object y itself occupies a variable of 4byte member object is contained in object Y
; 22:y Y;
Lea ECX, DWORD PTR _Y$[EBP]; The first address of object Y is deposited in ecx
Call?? 0y@ @QAE @xz; constructor that invokes object Y, the default constructor provided by the compiler
; 23:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
The constructor of object y is invoked, that is, the compiler provides the default constructor
The constructor for object y is the sink code:
Copy Code code as follows:
?? 0y@ @QAE @xz PROC; Y::y, Comdat
; _this$ = ecx
Push EBP
MOV EBP, esp
Push ECX
mov DWORD PTR _THIS$[EBP], the first address of object Y in Ecx;ecx
mov ecx, DWORD PTR _THIS$[EBP]
Add ecx, 4, plus 4 because the first address at the beginning of the object is stored in its own member variable i
Call?? 0x@ @QAE @xz; Call constructor for member object X
mov eax, DWORD PTR _THIS$[EBP]
mov esp, EBP
Pop EBP
RET 0
The constructor of object y calls the constructor of the member object X to initialize the member variable in the member object, and the member variable of object y itself is not initialized.
constructor sink encoding for member object x:
Copy Code code as follows:
?? 0x@ @QAE @xz PROC; X::x, Comdat
; _this$ = ecx
; 7:x () {
Push EBP
MOV EBP, esp
Push ECX
mov DWORD PTR _THIS$[EBP], the starting address of the member object X in ECX;ECX
; 8:i = 0;
mov eax, DWORD PTR _THIS$[EBP]; The starting address of the member object x to the EAX register
mov DWORD PTR [eax], 0; Initialize member object x in the amount member variable i
; 9:j = 0;
mov ecx, DWORD PTR _THIS$[EBP]; The starting address of the member object x to the ECX register
mov DWORD PTR [ecx+4], 0; Initialize member object x the amount member variable J plus 4 is the reason that J's address deviates from the member object x starting address 4byte (that is, the number of bytes in member object x)
; 10:}
mov eax, DWORD PTR _THIS$[EBP]
mov esp, EBP
Pop EBP
RET 0
But what happens if the member object x does not have any constructors?
The following is the C + + Source:
Copy Code code as follows:
Class X {
Private
int i;
Int J;
};
Class Y {
Private
int i;
X x;//x Member Object
};
int main () {
Y y;
}
The following is the main function sink encoding:
Copy Code code as follows:
; 17:int Main () {
Push EBP
MOV EBP, esp
Sub ESP, 12; Reserving 12byte space for an object
; 18:y Y;
; 19:}
xor eax, EAX
mov esp, EBP
Pop EBP
RET 0
As you can see, there is no function call in the main function, which means the compiler does not provide a default constructor.
What if the member object x has a constructor with parameters (that is, a non-default constructor), and object y does not have any constructors? At this point, the compiler will make an error.
The situation is similar to the previous one.
In combination with the above, it can be concluded that for a class that does not contain any constructors, and the compiler provides the default constructor, there are 3 different scenarios:
1 class itself function virtual member function or inherit from virtual base class
The base class of class 2 has constructors, and the base class constructor displays the defined default constructor (not compiler supplied), the constructor of the Jocky class has parameters (that is, a non-default constructor), and the compiler complains
3 This situation is similar to the previous one, the member object of the class has a constructor, and the constructor of the member object is the default constructor that displays the definition (not provided by the compiler), and the compiler complains if the member object's constructor has a parameter (that is, a non-default constructor).
The above reference to the "VC + in-depth detailed" Inside the knowledge points, but also their own analysis, welcome to correct