Совокупная безопасность инициализации в C++

Предположим, у меня есть следующая структура:

struct sampleData
{
       int x;
       int y;
};

И когда используется, я хочу инициализировать переменные sampleData введите в известное состояние.

sampleData sample = { 1, 2 } 

Позже я решаю, что мне нужны дополнительные данные, хранящиеся в моем sampleData структура, следующим образом:

struct sampleData
{
       int x;
       int y;
       int z;
};

Насколько я понимаю, инициализация двух полей осталась отz структура данных по-прежнему является допустимым оператором и будет скомпилирована, заполняя недостающие поля значениями по умолчанию.

Это понимание правильно? Я недавно работал в Аде, которая также позволяет инициализировать агрегат, но которая помечает аналогичную проблему как ошибку компиляции. Если предположить, что мои предположения о приведенном выше коде C++ верны, существует ли языковая конструкция, которая распознает пропущенные значения инициализации как ошибку?

4 ответа

Решение

Инициализация переменных таким способом поддерживается только в Aggregate Classes.

Если вы добавите конструктор (-ы), тогда проблема исчезнет, ​​но вам придется немного изменить синтаксис, и вы потеряете способность сохранять struct в union (между прочим).

struct sampleData
{
    sampleData(int x, int y) : x(x), y(y) {}
    int x;
    int y;
};

sampleData sample( 1, 2 );

Добавление z (и изменение конструктора) пометит sample( 1, 2 ) как ошибка компиляции.

Да, любые элементы, которые вы исключаете из списка инициализации, будут инициализированы нулем (для скалярных типов POD) или с использованием конструктора по умолчанию (для классов).

Соответствующий язык из стандарта C цитируется здесь:

[6.7.8.21] Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем элементов или членов агрегата или меньше символов в строковом литерале, используемом для инициализации массива известного размера, чем элементов в массиве, Остальная часть совокупности должна быть инициализирована неявно так же, как объекты, которые имеют статическую продолжительность хранения.

Я уверен, что кто-то более мотивированный, чем я мог найти соответствующий язык в одной из спецификаций C++...

Обратите внимание, что это означает, что скалярные элементы POD инициализируются так, как будто вы написали "= 0". Это означает, что он будет правильно инициализировать указатели в NULL и будет иметь значение 0.0, даже если их представления не будут равны нулю. Это также подразумевает, что это работает рекурсивно; если ваша структура содержит структуру, внутренняя структура также будет правильно инициализирована.

В качестве продолжения ответа Nemo со стандартом C, вот что говорит стандарт C++03:

§8.5.1 / 7:

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

§8.5 / 5:

Инициализировать значение объекта типа T средства:

  • если T является типом класса с объявленным пользователем конструктором, тогда конструктор по умолчанию для T называется (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
  • если T это тип класса без объединения без объявленного пользователем конструктора, тогда каждый нестатический член данных и компонент базового класса T инициализируется значением;
  • если T тип массива, тогда каждый элемент инициализируется значением;
  • в противном случае объект инициализируется нулями

Для инициализации нуля объекта типа T средства:

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

Почему бы не использовать

sampleData sample = { x: 1, y:2 } ;

?

Но вы все равно столкнетесь с проблемой z будучи инициализированным непредсказуемым значением, поэтому лучше определить конструктор, который устанавливает для всех переменных четко определенные значения.

Другие вопросы по тегам