Su g ++ 4.9.2 e 5.3.1, questo codice richiede alcuni secondi per compilare e produce un eseguibile 52.776 byte:std :: array con inizializzazione aggregato su g ++ genera enorme codice
#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;
}
crescente size
sembra aumentare il tempo di compilazione e le dimensioni eseguibili in modo lineare. Non riesco a riprodurre questo comportamento sia con clangore 3.5 o Visual C++ 2015. Utilizzando -Os
non fa differenza.
$ time g++ -O2 -std=c++11 test.cpp
real 0m4.178s
user 0m4.060s
sys 0m0.068s
Controllo del codice assembly rivela che l'inizializzazione a
viene srotolato, generando movl
istruzioni:
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)
questo avviene solo quando T
ha un costruttore non banale e l'array è inizializzato utilizzando {}
. Se eseguo una delle seguenti operazioni, g ++ genera un semplice ciclo:
- Rimuovi
S::S()
; - Rimuovere
S::S()
e inizializzareS::f
in-class; - Rimuovere l'inizializzazione aggregato (
= {}
); - compilare senza
-O2
.
Sono tutto per lo srotolamento del ciclo come ottimizzazione, ma non penso che sia molto buono. Prima di segnalare questo come un bug, qualcuno può confermare se questo è il comportamento previsto?
[edit: ho aperto a new bug per questo, perché gli altri non sembrano corrispondere. Erano più sul tempo di compilazione lungo che codegen strano.]
Wow. g ++ fa anche questo in 6.1. Ho fatto arrestare il compilatore ed emettere un avviso di bug di invio su Godbolt: https://godbolt.org/g/Ae75GH – NathanOliver
@NathanOliver Welp, questo lo conferma. Grazie. – isanae
Anche la gestione di gC di constexpr array è sospetta. Fa una cosa simile quando si inizializza un constexpr std :: array = make_array (...) dove make_array() è constexpr. –