之前在上C++的課的時候,印象中有那么一句話:
如果一個類沒有任何構造函數,那么編譯器會生成一個默認的構造函數
今天在看《深度探索C++對象模型》的第二章:“構造函數語意學”的時候發現之前聽到的說法是錯誤的。
比如說如下代碼:
class A {
public:
int a;
};
int main(void) {
A a;
a.a = 4;
A a2;
a2.a=5;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
按照之前的說法,類A沒有任何構造函數,編譯器會自動生成一個默認的構造函數,但事實是並不會。把上面的代碼反匯編后可以看到結果:
main:
push rbp
mov rbp, rsp #int main(void)
mov DWORD PTR [rbp-4], 4 #a.a = 4;
mov DWORD PTR [rbp-8], 5 #a2.a=5;
mov eax, 0 #return 0;
pop rbp
ret
1
2
3
4
5
6
7
8
我們可以發現這個類的對象被直接拿來用了,沒有調用任何構造函數,也沒有任何的初始化。
根據《深度探索C++對象模型》書上的說法,編譯器只在一定需要默認構造函數時,才會創建默認構造函數,比如說:
class A {
public:
A() {a = 0; }
int a;
};
class B : public A {
A _tmp;
};
int main(void) {
B b;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
在類B對象初始化時,類B對象中存在一個需要默認構造函數進行初始化的類A對象,那么類B對象必須要有默認構造函數,因此編譯器在迫不得已的情況下創建了類B對象的默認構造函數。
反匯編可以看到類B的默認構造函數:
A::A() [base object constructor]:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], 0
nop
pop rbp
ret
B::B() [base object constructor]:
push rbp
mov rbp, rsp
sub rsp, 16
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call A::A() [base object constructor]
mov rax, QWORD PTR [rbp-8]
add rax, 4
mov rdi, rax
call A::A() [complete object constructor]
nop
leave
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-8]
mov rdi, rax
call B::B() [complete object constructor]
mov eax, 0
leave
ret
————————————————
版權聲明:本文為CSDN博主「zhangpeterx」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhangpeterx/article/details/102762410
