Ошибка C4592: символ будет динамически инициализирован. VS2015.1 static const std::vector поле

после обновления VS2015.1 следующий код больше не компилируется:

class testClass
{
static const std::vector<int> test;
};

инициализации

const std::vector<int> testClass::test =
{
    1,2
};

с ошибкой:

ошибка C4592: 'test': символ будет динамически инициализирован (ограничение реализации)

это ошибка или что-то изменилось в компиляторе?

Ответы

Ответ 1

Компилятор VС++ здесь.

Ответ Питера Рудермана почти правильный. Предупреждение действительно предназначалось для объектов constexpr, где в инициализации задействован вызов конструктора constexpr. В Update1 мы можем теперь статически инициализировать литералы и некоторые нелитеральные типы с конструкторами constexpr, но не все. В частности, наличие виртуальных функций-членов предотвратит статическую инициализацию, даже если тип имеет конструктор constexpr и снабжен постоянным инициализатором. Предупреждение предназначалось для диагностики таких случаев. К сожалению, произошла ошибка, которая вызвала его, когда типы выражений в списке инициализаторов имели конструкторы constexpr (в примере OP std::vector нет, но std:: initializer_list делает). Это предупреждение можно смело игнорировать, поскольку компилятор ничего не делает по-другому.

Мы исправили ошибку, но, к сожалению, ее слишком поздно было включить в Обновление 1. В любом случае необходимость этого предупреждения должна исчезнуть, когда мы выполним более полную реализацию постоянной инициализации (3.6.2).

Танвейер Гани Команда Visual С++.

Ответ 2

К сожалению, мне не хватает "репутации" для комментариев, поэтому я добавлю свои комментарии здесь.

@Peter Ruderman: полная поддержка постоянной инициализации включена в список. Я не могу сказать, будет ли это внесено в обновление 2, но мы сделаем все возможное. Вы получаете предупреждение для типа без конструкторов constexpr из-за ошибки, которая обнаружила другой конструктор constexpr в дереве вызовов. Обычно это происходит из std:: initializer_list < > .

@Peter Ruderman: Кроме того, небольшая коррекция: для статических объектов времени жизни, инициализированных вызовом конструктора constexpr, статическая инициализация требуется только в том случае, если инициализатор является инициализатором константы, то есть состоит только из постоянных выражений. Update1 делает это, но не для типов, содержащих виртуальные функции.

Также: в OP-коде статическая инициализация не требуется, хотя я полагаю, что компилятор может сделать это по причинам качества реализации. Это связано с тем, что вместо константы был использован "const", последний требует статической инициализации.

Повторить: отключить это предупреждение вполне разумно (и безопасно).

Ответ 3

в моем случае я решил это с помощью std:: array, и он работает для меня, но в общем случае я полагаю, что предупреждение отключено - это решение

#pragma warning( disable : 4592)

Ответ 4

Я считаю, что предупреждение инициируется новой логикой для обнаружения, когда компилятор генерирует динамические инициализаторы для статических объектов с конструкторами constexpr. В этом конкретном случае нет смысла поднимать его, потому что std::vector не имеет конструкторов constexpr. Так что ошибка № 1.

Ошибка № 2 заключается в том, что статические объекты с конструкторами constexpr по-прежнему получают динамические инициализаторы. Это должно было быть исправлено в обновлении 1, но, по-видимому, Microsoft не смогла это сделать.

Когда вы инициализируете тип конструктором constexpr на уровне модуля, компилятор должен иметь возможность запускать сам конструктор и встраивать полностью построенный объект непосредственно в ваш файл изображения. Однако это не работает в VC. Вместо этого он создаст динамический инициализатор и инициализирует объект во время выполнения, когда ваша программа начнется.

Предупреждение пытается сделать эту проблему видимой. Это безопасно игнорировать в большинстве случаев, и это, безусловно, безопасно игнорировать в этом конкретном случае.