假设我有以下代码
class C {
public:
explicit C() :
member()
{}
private:
int member;
};
我想将member()
的值member
初始化为零。
我的问题是:这在运行时会产生任何开销吗?还是在编译时以某种特定方式完成了?
答案 0 :(得分:5)
简而言之:开销很小,但是编译器很聪明!
长版:
必须将内存清零,这需要一些工作。您可以看到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;
}
然后,构造函数主体将内联到main函数中,但您仍会找到零指令
mov dword ptr [rsp], 0
还要注意,根据实例化之后的代码,编译器可能会进一步优化。例如,如果您查看
的输出C c;
c.member = expression;
然后您将看到零分配将从输出中删除。
答案 1 :(得分:2)
这取决于编译器及其优化。假设优化级别为无,那么编译器很可能会生成一些用于初始化成员变量的指令。此代码已优化,例如对于使用-O1的gcc。
比较成员初始化和没有成员初始化之间的区别:
https://godbolt.org/g/ZE62PP与https://godbolt.org/g/msRQtp