编译以下代码
height = input
进行集会
int main() {
return 0;
}
https://gcc.godbolt.org/z/oQvRDd
如果现在包含main:
xorl %eax, %eax
ret
iostream
此程序集已创建。
#include <iostream>
int main() {
return 0;
}
完全优化已打开(-O3)。 https://gcc.godbolt.org/z/EtrEX8
有人可以解释一下,为什么包括未使用的标头会更改二进制文件。什么是main:
xorl %eax, %eax
ret
_GLOBAL__sub_I_main:
subq $8, %rsp
movl $_ZStL8__ioinit, %edi
call std::ios_base::Init::Init() [complete object constructor]
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
jmp __cxa_atexit
?
答案 0 :(得分:33)
每个包含<iostream>
的翻译单元都包含ios_base::Init
对象的副本:
static ios_base::Init __ioinit;
此对象用于初始化标准流(std::cout
及其朋友)。此方法称为Schwarz Counter,可确保始终在首次使用标准流之前初始化标准流(已提供iostream
标头)。
该函数_GLOBAL__sub_I_main
是编译器为每个翻译单元生成的代码,该代码调用该翻译单元中的全局对象的构造函数,并安排在出口处调用相应的析构函数调用。在调用main
之前,C ++标准库启动代码将调用此代码。
答案 1 :(得分:23)
包含iostream
标头的作用是添加静态std::ios_base::Init
对象的定义。该静态对象的构造函数将初始化标准流对象std::cout
,std::cerr
等。
这样做的原因是避免静态初始化顺序的惨败。这样可以确保跨翻译单元正确地初始化流对象。