На г ++ 4.9.2 и 5.3.1, этот код занимает несколько секунд, чтобы компилировать и производит 52776 байт исполняемый файл:станд :: массива с совокупной инициализацией на г ++ генерирует огромный код
#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
.
Я все для разворачивания цикла в качестве оптимизации, но я не думаю, что это очень хорошо. Прежде чем сообщать об этом как об ошибке, может ли кто-нибудь подтвердить, является ли это ожидаемым поведением?
[edit: Я открыл a new bug для этого, потому что другие, похоже, не совпадают. Они были больше о длительном времени компиляции, чем о странном кодеге.]
Ничего себе. g ++ делает это и в 6.1. Я получил компилятор для сбоя и выдаю предупреждение об ошибке отправки на godbolt: https://godbolt.org/g/Ae75GH – NathanOliver
@NathanOliver Welp, это подтверждает его. Благодарю. – isanae
Обработка gcc массива constexpr также является подозрительной. Это похоже на инициализацию constexpr std :: array = make_array (...), где make_array() является constexpr. –