对于以下代码:
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>
特别之处?
可能相关的一句话是:
根据静态初始化顺序,可以确保在不首次构造ios_base :: Init类型的对象的情况下正确构造和初始化cout,并包括将此类对象至少具有静态持续时间的初始化算作一次初始化。
这个MSDN论坛链接提供了一个代码片段:
#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
}
相关报价:
现在,前面提到的运行时代价是:必须在您自己的任何代码使用全局对象之前初始化全局对象;这是标准所保证的。像任何其他全局对象一样,必须将它们初始化一次,并且只能初始化一次。通常,这是通过上述结构完成的,正是出于这个原因,在标准中指定了嵌套类ios_base :: Init。
和标准报价:
根据§27.3/ 2:“构造了[std :: cin,std :: cout等]对象,并在ios_base :: Init类的对象首次出现之前或期间的某个时间建立了关联。构造,并且无论如何在主体开始执行之前。”
ios_base::Init
正如乔浩的评论所暗示的那样,罪魁祸首确实是排队。因此,如果MSDN链接是正确的,那么这意味着<iostream>
是特别为这个原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句