简而言之:开销很小但编译器很聪明!
长版:
内存必须清零,这需要一些工作。可以看到当你compile your class to assembly时,加上一个简单的驱动函数
int main() { C c; }
使用-O1 优化。
然后没有成员初始化,生成的代码是这样的
main: # @main
push rax
mov rdi, rsp
call C::C() [base object constructor]
xor eax, eax
pop rcx
ret
C::C() [base object constructor]: # @C::C() [base object constructor]
ret
在最后两行中,您可以看到构造函数是微不足道的。当你用括号添加成员初始化时,它变成了
C::C() [base object constructor]: # @C::C() [base object constructor]
mov qword ptr [rdi], 0
ret
mov 指令将某个特定内存位置的DWORD 设置为零。 DWORD 是 32 位的。
编译器可能能够组合初始化。例如,如果您添加第二个int:
class C {
public:
explicit C()
: member(), anotherMember()
{}
private:
int member;
int anotherMember; // <====
};
int main() {
C c;
}
然后DWORD 更改为QWORD,因此它实际上同时将两个整数归零。即使使用更高的优化级别,您也会看到这一点,例如,当您添加编译器无法优化的内容时,例如从 stdin 和 compile this with -O2 读取的内容时
#include <iostream>
class C {
public:
explicit C()
: member()
{}
int member;
};
int main() {
int x;
C c;
std::cin >> c.member;
}
然后构造函数体将被内联到主函数中,但你仍然会找到零指令
mov dword ptr [rsp], 0
还要注意,根据实例化后的代码,编译器可能会进一步优化。例如,如果您查看
的输出
C c;
c.member = expression;
然后你会看到零赋值将从输出中删除。