Несовместимость инициализации Visual C++ с gcc и clang
Следующий кусок кода печатает 0
скомпилирован с vC++ и печатает 1
скомпилировано с g++ или clang++:
#include <iostream>
#include <vector>
struct S
{
S() = default;
std::vector<int> v{0};
};
int main()
{
std::vector<S> s{{}};
std::cout << s.front().v.size() << std::endl;
}
Это ошибка в vC++?
Если задан пользовательский конструктор (S() {};
вместо S() = default;
) vC++ начинает печатать 1
тоже.
2 ответа
При чтении стандарта (C++11 n3485), 12.6.2/9
говорится, что:
Если данный нестатический элемент данных имеет
brace-or-equal-initializer
иmem-initializer
инициализация, указаннаяmem-initializer
выполняется, и нестатический член данныхbrace-or-equal-initializer
игнорируется
Таким образом, возникает вопрос, если default
т.е. неявно определенный конструктор содержит mem-initializer
или нет.
Раздел 12.1/6
состояния:
Неявно определенный конструктор по умолчанию выполняет набор инициализаций класса, которые будут выполняться пользовательским конструктором по умолчанию для этого класса без
ctor-initializer
(12.6.2) и пустойcompound-statement
,
Это будет означать, что неявно сгенерированный (по умолчанию) конструктор не имеет mem-initializer
и должен действительно использовать инициализатор в классе (brace-or-equal-initializer
в приведенной цитате).
MSVC здесь не прав (не удивительно, правда).
Это не ответ, а комментарий, требующий кода.
Я думаю, что следующее иллюстрирует различия в компиляторе:
#include <iostream>
#include <vector>
struct S
{
S() = default;
std::vector<int> v = std::vector<int>(13);
};
int main()
{
std::vector<S> s{{}};
std::cout << s.front().v.size() << std::endl;
}
Здесь g++ MinGW 5.1.0 сообщает о 13 элементах, а MSVC 2015 обновление 2 сообщает о 0 элементах.
Т.е. g ++ использует инициализатор, указанный в классе, а MSVC использует тот, который указан в объявлении s
, Для меня это выглядит как проблема с g ++. Но я не уверен: единственная уверенность в том, что оба не могут быть правы.