之前在上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

04-24 18:40