自 C++11 以来的 C++ 标准保证 std::cout
是“可用于具有有序初始化的静态对象的构造函数和析构函数(只要在定义对象之前包含)”(引用自 cppreference.com )。我在这里不详细介绍(例如 std::ios_base::Init
的角色等)。例如,参见Is it safe to use standard library functions before main() has been called?
然而,这个保证意味着只要<iostream>
包含在内,编译器必须确保将一些初始化代码添加到目标文件中(除非编译器/链接器存在一些优化可以避免这种情况)。我用 Godbolt Compiler Explorer 尝试了这一点:对于 ARM gcc 5.4(linux) 和 -O2,以下代码
int main() {
}
编译为
main:
mov r0, #0
bx lr
而代码
#include <iostream>
int main() {
}
编译为
main:
mov r0, #0
bx lr
_GLOBAL__sub_I_main:
stmfd sp!, {r4, lr}
ldr r4, .L4
mov r0, r4
bl std::ios_base::Init::Init() [complete object constructor]
mov r0, r4
ldr r2, .L4+4
ldr r1, .L4+8
bl __aeabi_atexit
ldmfd sp!, {r4, lr}
bx lr
.L4:
.word .LANCHOR0
.word __dso_handle
.word _ZNSt8ios_base4InitD1Ev
.LANCHOR0 = . + 0
因此,仅包含 <iostream>
增加代码大小和初始化时间。对于单个文件,影响可能可以忽略不计。然而,在 IMO 中,不必要地将此类包含指令添加到广泛使用的库头文件中仍然会被视为可以避免的资源浪费。我将其视为保持包含指令干净的另一个(即使不是强有力的)论据。
一些附加说明:
- 可能会对符号表大小产生影响。我对此不感兴趣 - 我感兴趣的是代码大小、数据大小和性能。
- 我知道,即使从未调用内联函数,非优化编译器也可能会为内联函数生成代码(外行)。您可以假设已启用优化来防止这种情况发生。
最佳答案
这实际上并不在标准范围内,但 IOStream 的合理实现确实要求此初始化代码(否则 std::cout
将不可用,尽管有一些其他共享的静态状态)。
我个人没有在库的其他部分遇到过这种情况,而且我想不出容器或算法这样做的原因。我可以想象一些线程子系统可能涉及一些预先初始化。
最终,您了解自己的工具链和平台的唯一方法就是尝试。一个快速脚本会依次生成包括各种标准头文件的 C++ 源文件,依次将它们传递给编译器并检查生成的程序集,然后以简短的顺序显示答案。
关于c++ - 哪个 C++ 标准包含文件强制将代码/数据添加到目标文件中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55969087/