以下代码:
int main()
{
}
对于g++ -pedantic -Wall -O3 -S -o test.asm test.cpp && cat test.asm
,程序集输出不出所料。如果我在顶部gcc -x c ... test c
#include <stdio.h>
,则输出相同,但标签名称除外。实际上,如果它处于C++
或C
模式并不重要。其他标题如<string>
,<vector>
,<algorithm>
,<ostream>
等会产生相同的结果。
.file "test.cpp"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.section .text.startup,"ax",@progbits
.LHOTB0:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE0:
.size main, .-main
.section .text.unlikely
.LCOLDE0:
.section .text.startup
.LHOTE0:
.ident "GCC: (GNU) 4.9.0 20131223 (experimental)"
.section .note.GNU-stack,"",@progbits
但是只要你添加#include <iostream>
,它就会爆炸(省略相同的部分):
.section .text.unlikely
.LCOLDE0:
.section .text.startup
.LHOTE0:
.section .text.unlikely
.LCOLDB1:
.section .text.startup
.LHOTB1:
.p2align 4,,15
.type _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB1027:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZStL8__ioinit, %edi
call _ZNSt8ios_base4InitC1Ev
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp __cxa_atexit
.cfi_endproc
.LFE1027:
.size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
.section .text.unlikely
.LCOLDE1:
.section .text.startup
.LHOTE1:
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_main
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.hidden __dso_handle
.ident "GCC: (GNU) 4.9.0 20131223 (experimental)"
.section .note.GNU-stack,"",@progbits
是什么让<iostream>
特别?
可能相关的一个引用是:
就静态初始化顺序而言,cout是保证的 不迟于第一次正确构建和初始化 构造ios_base :: Init类型的对象,包含 计为至少一次这种对象的初始化 静态持续时间。
答案 0 :(得分:2)
此MSDN forum link提供了一个代码段:
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
....
// this is explained below
static ios_base::Init __foo; // not its real name
}
相关引用:
现在,前面提到的运行时惩罚:全局对象必须 在您自己的代码使用它们之前进行初始化;这是 由标准保证。像任何其他全球对象一样,它们必须如此 初始化一次且仅一次。这通常用a来完成 像上面那样构造,嵌套类ios_base :: Init是 由于这个原因,在标准中规定了。
根据§27.3/ 2:“对象[std :: cin,std :: cout等]是 构建,并在之前的某个时间建立协会 到或在第一次使用类ios_base :: Init的对象时 构造,并且无论如何在主体开始之前 执行“。
罪魁祸首确实是ios_base::Init
行,正如cHao的评论所暗示的那样。因此,如果msdn链接正确,则表示<iostream>
因此special为{{3}}。