按需合成构造函数
复制、默认构造都是按需生成的。对于平凡的情况不需要生成,只是在语意上满足“拥有构造函数”的含义。
x86-64 gcc 13.1 -std=c++20
struct Point {
int x;
int y;
Point() = default; // 即便显式声明了默认构造函数,也不会合成
};
int main() {
auto some_point = Point{}; // {}初始化对聚合类有清零的效果
}
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-4], 0
mov eax, 0
pop rbp
ret
修改 Point 的定义:
struct Point {
int x{}; // 只修改了这里,结果合成了默认构造函数
int y;
Point() = default;
};
int main() {
auto some_point = Point{};
}
Point::Point() [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
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-4], 0
lea rax, [rbp-8]
mov rdi, rax
call Point::Point() [complete object constructor]
mov eax, 0
leave
ret
接下来删掉默认构造函数的声明:
struct Point {
int x{};
int y;
// 删掉了默认构造函数声明,结果不再合成默认构造函数
};
int main() {
auto some_point = Point{};
}
main:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
mov eax, 0
pop rbp
ret
构造函数和成员默认值同时出现时,就会合成默认构造函数。这个和书中的描述是相符的,因为有成员默认值时,默认构造函数需要特别处理一些内容。
接下来:
struct Point {
int x{};
int y;
};
int main() {
auto some_point = Point(); // 注意花括号变成了圆括号
}
Point::Point() [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
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-4], 0
lea rax, [rbp-8]
mov rdi, rax
call Point::Point() [complete object constructor]
mov eax, 0
leave
ret
显式使用构造函数相当于声明了构造函数。
不过但凡用上 -O1
级别的优化,空的默认构造函数就可以被内联。