Инициализация нуля массива C++: это ошибка или это правильно?
Примечание. Мы говорим о (предположительно) C++98-совместимых компиляторах здесь. Это не вопрос C++11.
У нас странное поведение в одном из наших компиляторов, и мы не уверены, что это нормально или это ошибка компилятора:
// This struct has a default constructor
struct AAA
{
AAA() : value(0) {}
int value ;
} ;
// This struct has a member of type AAA and an array of int, both surrounded
// by ints
struct BBB
{
int m_a ;
AAA m_b ;
int m_c ;
int m_d[42] ;
} ;
Когда BBB инициализируется как таковой:
BBB bbb = {0} ;
Мы ожидали, что все члены POD BBB (включая m_d, массив целых чисел) будут инициализированы нулями, и будут созданы все не-POD члены BBB.
Это работало на собственном компиляторе AIX, на Linux/GCC-3.4, на Windows/VisualC++... Но не на Solaris/SunStudio, где только члены без массивов инициализируются нулями.
Мы провели небольшое исследование стандарта C++ 98 (черновик документа), в котором обнаружили следующее:
[12.6.1 - 2]
Когда агрегат (независимо от того, является ли он классом или массивом) содержит члены типа класса и инициализируется заключенным в скобки списком инициализаторов (8.5.1), каждый такой член инициализируется копией (см. 8.5) соответствующим выражением присваивания. Если в списке инициализаторов меньше инициализаторов, чем членов агрегата, каждый элемент, не инициализированный явно, должен инициализироваться по умолчанию (8.5).
Затем:
[8.5 - 5]
Инициализировать нулевое хранилище для объекта типа T означает:
- если T является скалярным типом (3.9), в хранилище устанавливается значение 0 (ноль), преобразованное в T;
- если T является типом класса, не являющимся объединением, память для каждого нестатического члена данных и каждого подобъекта базового класса инициализируется нулями;
- если T является типом объединения, хранилище для его первого элемента данных 89) инициализируется нулями;
- если T является типом массива, память для каждого элемента инициализируется нулями;
- если T является ссылочным типом, инициализация не выполняется.
А потом:
По умолчанию инициализировать объект типа T означает:
- если T является типом класса, отличным от POD (раздел 9), вызывается конструктор по умолчанию для T (и инициализация является некорректной, если у T нет доступного конструктора по умолчанию);
- если T является типом массива, каждый элемент инициализируется по умолчанию;
- иначе хранилище для объекта инициализируется нулями.
Как я это прочитал: SunStudio должен инициализировать нулем массив целых чисел (BBB::m_d)
Странная вещь: если мы удаляем конструктор по умолчанию из AAA, то все в BBB инициализируется нулями.
ВОПРОС: Стандартно ли поведение SunStudio, когда ему не удается инициализировать нулем массив целых чисел структуры, содержащей не POD? Или это ошибка компилятора?
3 ответа
Это действительно ошибка с Sun/Solaris. То, что вы написали, действительно то, что должно произойти, и вы правы во всем, что пишете.
Кажется, это ошибка - у меня нет опыта работы с компиляторами Solaris, но все остальные компиляторы, с которыми я работал, позволяют такую инициализацию.
Я хотел бы предложить, чтобы обойти проблему, будучи более явным:
BBB bbb = {0, 0, 0, {0} };
Это явно ошибка в Sun CC. Стандарт понятен, и вы понимаете его правильно.