Почему этот авто-векторный анализатор заботится о конструкторах/деструкторах?

Вот SSCCE:

class Vec final {
    public:
        float data[4];

        inline Vec(void) {}
        inline ~Vec(void) {}
};
Vec operator*(float const& scalar, Vec const& vec) {
    Vec result;
    #if 1
        for (int k=0;k<4;++k) result.data[k]=scalar*vec.data[k];
    #else
        float const*__restrict src =    vec.data;
        float      *__restrict dst = result.data;
        for (int k=0;k<4;++k) dst[k]=scalar*src[k];
    #endif
    return result;
}

int main(int /*argc*/, char* /*argv*/[]) {
    Vec vec;
    Vec scaledf = 2.0f * vec;
    return 0;
}

При компиляции MSVC 2013 сообщает мне (/Qvec-report:2), что

main.cpp(11): информация C5002: цикл не векторизован по причине "1200"

Это означает, что "[l] oop содержит зависящие от цикла данные зависимостей".

Я заметил, что комментирование конструктора или деструктора для Vec (редактирование: или по умолчанию их, например, Vec()=default;) заставляет его успешно векторизовать. Мой вопрос: почему?


Примечание. Переключение #if также заставит его работать. Важно __restrict.
Примечание. Изменение float const& scalar на float const scalar приводит к тому, что векторизация сообщает 1303 (векторизация не будет выигрышной), я подозреваю, потому что эта ссылка может быть передана непосредственно в регистр SSE, тогда как значение pass-by-value нуждается в другом копия.

Ответ 1

Почему вы объявляете пустой не виртуальный деструктор inline ~Vec(void) {} с пустым конструктором по умолчанию inline Vec(void) {}?

В результате компилятор не создает конструктор копии по умолчанию. Таким образом, код return result; не может быть скомпилирован без него, потому что для этого требуется скопировать результат во временный возвращаемый объект (это может быть не так, как вы хотите).

Определите конструктор копирования или не определите пустой конструктор и деструктор вообще.