Совокупная безопасность инициализации в C ++ - PullRequest
8 голосов
/ 09 июня 2011

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

struct sampleData
{
       int x;
       int y;
};

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

sampleData sample = { 1, 2 } 

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

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

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

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

Ответы [ 4 ]

5 голосов
/ 09 июня 2011

Инициализация переменных таким образом поддерживается только с 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 ) как ошибку компиляции.

4 голосов
/ 09 июня 2011

В качестве ответа на ответ Немо со стандартом C, вот что говорит стандарт C ++ 03:

§8.5.1 / 7:

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

§8.5 / 5:

К значение-инициализировать объект типа T означает:

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

К инициализируется нулями anобъект типа T означает:

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

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

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

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

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

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

0 голосов
/ 09 июня 2011

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

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

?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...