Ошибка 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. Вместо этого он создаст динамический инициализатор и инициализирует объект во время выполнения, когда ваша программа начнется.
Предупреждение пытается сделать эту проблему видимой. Это безопасно игнорировать в большинстве случаев, и это, безусловно, безопасно игнорировать в этом конкретном случае.