У меня есть класс с членом массива, который я хотел бы инициализировать для всех нулей.
class X
{
private:
int m_array[10];
};
Для локальной переменной существует простой способ инициализации нуля (см. Вот):
int myArray[10] = {};
Также ученик m_array
очевидно, что его нужно инициализировать, так как инициализируемые по умолчанию int будут просто оставлять случайный мусор, как объяснено Вот.
Тем не менее, я вижу два способа сделать это для массива-члена:
С круглыми скобками:
public:
X()
: m_array()
{}
С фигурными скобками:
public:
X()
: m_array{}
{}
Правильны ли оба? Есть ли разница между ними в C ++ 11?
Инициализация любого члена с ()
выполняет инициализацию значения.
Инициализация любого типа класса конструктором по умолчанию с {}
выполняет инициализацию значения.
Инициализация любого другого типа агрегата (включая массивы) с {}
выполняет инициализацию списка и эквивалентно инициализации каждого члена агрегата с помощью {}
,
Инициализация любого ссылочного типа с {}
создает временный объект, который инициализируется из {}
и связывает ссылку на это временное.
Инициализация любого другого типа с {}
выполняет инициализацию значения.
Следовательно, для почти всех типов инициализация из {}
даст тот же результат, что и инициализация значения. Вы не можете иметь массивы ссылок, поэтому они не могут быть исключением. Вы может быть уметь создавать массивы типов агрегатных классов без конструктора по умолчанию, но компиляторы не согласны с точными правилами. Но чтобы вернуться к вашему вопросу, все эти угловые случаи не имеют для вас никакого значения: для вашего конкретного типа элемента массива они имеют точно такой же эффект.
Типы инициализации могут быть довольно утомительными, но в этом случае они тривиальны. За:
public:
X()
: m_array()
{}
так как список_выражений между круглыми скобками пусто, происходит инициализация значения. Аналогично для:
public:
X()
: m_array{}
{}
происходит инициализация списка, а затем инициализация значения, так как скобка-INIT-лист пустой.
Чтобы дать более полный ответ, давайте рассмотрим §8.5 N4140.
- Если для объекта не указан инициализатор, объект
по умолчанию инициализируется. При хранении для объекта с автоматическим или
динамическая длительность хранения получается, объект имеет неопределенный
значение, и если инициализация не выполняется для объекта, то
объект сохраняет неопределенное значение, пока это значение не будет заменено
(5.17).
это неопределенное значение это то, что вы называете значениями мусора.
к нулевой инициализации объект или ссылка типа
T
средства:— если T является типом массива, каждый элемент инициализируется нулями
к Значение инициализации объект типа
T
средства:— если T является (возможно, cv-квалифицированным) типом класса … тогда объект инициализируется по умолчанию; …
— если T является типом массива, то каждый элемент инициализируется значением;
— иначе объект инициализируется нулями.
Семантика инициализаторов следующая. …
— Если инициализатор (без скобок) приготовился-INIT-лист, объект или ссылка инициализируются списком (8.5.4).— Если инициализатором является (), объект инициализируется значением.
Пока ясно, что инициализация значения сделает каждый элемент массива нулевым, так как int
это не тип класса. Но мы еще не рассмотрели инициализацию списка и агрегатную инициализацию, поскольку массив является агрегатом.
§8.5.4:
Инициализация списка объекта или ссылки типа
T
определяется следующим образом:— Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).
И вернемся к §8.5.1:
- Если есть меньше инициализатора-статьи в списке, чем там
являются членами в совокупности, то каждый член не явно
инициализируется должен быть инициализирован из его скобки или равно-инициализатор
или, если нет скобки или равно-инициализатор, из пустого
список инициализаторов (8.5.4).
И мы снова заканчиваем §8.5.4:
Инициализация списка объекта или ссылки типа
T
определяется следующим образом:— В противном случае, если в списке инициализатора нет элементов, объект инициализируется значением.
Поскольку пересмотр (чернового) стандарта может перевести дух от вас, я рекомендую cppreference как это ломает это довольно хорошо.
cppreference:
Проект стандарта:
Круглые скобки работают в C ++ 98 и требуют нулевой инициализации, что вам и нужно. Я проверил на gcc 4.3. Редактировать: удалено неверное утверждение о C ++ 11. Я также подтвердил, что пустые скобки выполняют инициализацию пустого списка, используя clang 3.4 с -std = c ++ 11.