Подтвердить что ты не робот

Странное поведение GCC

Учитывая следующий код С++:

struct vertex_type {
    float x, y, z;

    //vertex_type() {}
    //vertex_type(float x, float y, float z) : x(x), y(y), z(z) {}
};

typedef struct {
    vertex_type vertex[10000];
} obj_type;

obj_type cube = {
    {
        {-1, -1, -1},
        {1, -1, -1},
        {-1, 1, -1},
        {1, 1, -1},

        {-1, -1, 1},
        {1, -1, 1},
        {-1, 1, 1},
        {1, 1, 1}
    }
};

int main() {
    return 0;
}

Когда я добавил конструкторы (в настоящее время прокомментированные) в структуру vertex_type, это резко увеличилось на 10-15 секунд во время компиляции. В тупик я посмотрел на сборку, сгенерированную gcc (используя -S), и заметил, что размер кода-gen был в несколько сотен раз больше, чем раньше.

...
movl    $0x3f800000, cube+84(%rip)
movl    $0x3f800000, cube+88(%rip)
movl    $0x3f800000, cube+92(%rip)
movl    $0x00000000, cube+96(%rip)
...
movl    $0x00000000, cube+119996(%rip)
...

Оставив определение конструктора, сгенерированная сборка была совершенно другой.

.globl cube
    .data
    .align 32
    .type   cube, @object
    .size   cube, 120
cube:
    .long   3212836864
    .long   3212836864
    .long   3212836864
    .long   1065353216
    .long   3212836864
    .long   3212836864
    .long   3212836864
    .long   1065353216
    .long   3212836864
    .long   1065353216
    .long   1065353216
    .long   3212836864
    .long   3212836864
    .long   3212836864
    .long   1065353216
    .long   1065353216
    .long   3212836864
    .long   1065353216
    .long   3212836864
    .long   1065353216
    .long   1065353216
    .long   1065353216
    .long   1065353216
    .long   1065353216
    .zero   24
    .text

Очевидно, что существует значительная разница в коде, сгенерированном компилятором. Почему это? Кроме того, почему gcc нуля все элементы в одной ситуации, а не другие?

изменить Я использую следующие флаги компилятора: -std=c++0x с g++ 4.5.2.

4b9b3361

Ответ 1

Это давняя отсутствующая оптимизация в GCC. Он должен иметь возможность генерировать один и тот же код для обоих случаев, но он не может.

Без конструкторов ваш vertex_type представляет собой структуру POD, которую GCC может инициализировать статические/глобальные экземпляры во время компиляции. С помощью конструкторов лучшее, что он может сделать, это генерировать код для инициализации глобального при запуске программы.

Ответ 2

Если у вас есть пользовательский конструктор, компилятор должен вызвать его для всего создаваемого им вектора. Если вы не пишете свой собственный, по умолчанию используется сгенерированный конструктор. Но поскольку ни один тип не является сложным, его просто не нужно называть. И массив хранится как постоянная таблица в двоичном формате.

Попробуйте вставить свой конструктор по умолчанию и пусть он пуст. Конечно, он может работать только с включенной оптимизацией