在克++ 4.9.2和5.3.1,此代码需要几秒钟来编译,并产生一个52776字节的可执行:的std ::阵列与克++集合初始化产生巨大代码
#include <array>
#include <iostream>
int main()
{
constexpr std::size_t size = 4096;
struct S
{
float f;
S() : f(0.0f) {}
};
std::array<S, size> a = {}; // <-- note aggregate initialization
for (auto& e : a)
std::cerr << e.f;
return 0;
}
增加size
似乎线性增加编译时间和可执行文件大小。我无法用clang 3.5或Visual C++ 2015重现此行为。使用-Os
没有任何区别。
$ time g++ -O2 -std=c++11 test.cpp
real 0m4.178s
user 0m4.060s
sys 0m0.068s
检查汇编代码表明的a
初始化被展开,生成 movl
指令:
main:
.LFB1313:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
subq $16384, %rsp
.cfi_def_cfa_offset 16400
movl $0x00000000, (%rsp)
movl $0x00000000, 4(%rsp)
movq %rsp, %rbx
movl $0x00000000, 8(%rsp)
movl $0x00000000, 12(%rsp)
movl $0x00000000, 16(%rsp)
[...skipping 4000 lines...]
movl $0x00000000, 16376(%rsp)
movl $0x00000000, 16380(%rsp)
这只发生时T
具有一个非平凡的构造和阵列被初始化使用{}
。如果我执行以下任何操作,g ++会生成一个简单的循环:
- 删除
S::S()
; - 删除
S::S()
并初始化S::f
课堂上; - 删除聚合初始化(
= {}
); - 编译时没有
-O2
。
我所有的循环展开作为优化,但我不认为这是一个很好的。在我将此作为错误报告之前,有人可以确认这是否是预期的行为?
[编辑:我已经为此打开a new bug,因为其他人似乎不匹配。他们更多的是编译时间长于奇怪的代码。]
哇。 g ++在6.1中也是这样做的。我得到了编译器将崩溃,并就godbolt一个提交错误警告:https://godbolt.org/g/Ae75GH – NathanOliver
@NathanOliver韦尔普,这有点儿证实了这一点。谢谢。 – isanae
gcc处理constexpr数组也是可疑的。它在初始化constexpr std :: array时做类似的事情 = make_array(...)其中make_array()是constexpr。 –