对于以下代码:
int main()
{
}
对于g++ -pedantic -Wall -O3 -S -o test.asm test.cpp && cat test.asm
, assembly 输出毫无疑问是干净的。如果我这样做gcc -x c ... test c
与 #include <stdio.h>
在顶部,除了标签名称之外,输出相同。其实是否在 C++
中并不重要或C
模式。其他 header 如 <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>
特别吗?
可能相关的一个引用是:
In terms of static initialization order, cout is guaranteed to be properly constructed and initialized no later than the first time an object of type ios_base::Init is constructed, with the inclusion of counting as at least one initialization of such objects with static duration.
最佳答案
这个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
}
相关引用:
Now, the runtime penalty mentioned previously: the global objects must be initialized before any of your own code uses them; this is guaranteed by the standard. Like any other global object, they must be initialized once and only once. This is typically done with a construct like the one above, and the nested class ios_base::Init is specified in the standard for just this reason.
还有standard quote :
According to §27.3/2: "The objects [std::cin, std::cout, etc.] are constructed, and the associations are established at some time prior to or during first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution."
罪魁祸首确实是 ios_base::Init
行,如cHao的评论表明。因此,如果 msdn 链接正确,则意味着 <iostream>
是 special因此。
关于c++ - 为什么汇编输出中有这么多 iostream 的样板文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20779400/