Ответ 1
Это действительно ошибка с Sun/Solaris. То, что вы написали, действительно то, что должно случиться, и вы правы со всем, что вы пишете.
Примечание. Мы говорим о (предположительно) компиляторах, совместимых с С++ 98, здесь. Это не вопрос С++ 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 = {0} ;
Мы ожидали, что все члены POD BBB (включая m_d, массив ints) будут нуль-инициализированы и будут созданы все не-POD-элементы BBB.
Это работало на собственный компилятор AIX, на Linux/GCC-3.4, на Windows/VisualС++... Но не на Solaris/SunStudio, где инициализируются ноль-инициализация только членами не-массивов.
Мы провели небольшое исследование в стандарте С++ 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 является ссылочным типом, инициализация не выполняется.
И затем:
По умолчанию-initialize объект типа T означает:
- если T - тип класса не-POD (раздел 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
- , если T - тип массива, каждый элемент инициализируется по умолчанию;
- В противном случае хранилище для объекта инициализируется нулем.
Как я его читаю: SunStudio должен нуль инициализировать массив ints (BBB:: m_d)
Странная вещь: если мы удалим конструктор по умолчанию из AAA, тогда все в BBB инициализируется нулем.
ВОПРОС: Является ли поведение SunStudio стандартным, когда ему не удается инициализировать массив из ints структуры, содержащей не-POD? Или это ошибка компилятора?
Это действительно ошибка с Sun/Solaris. То, что вы написали, действительно то, что должно случиться, и вы правы со всем, что вы пишете.
Это явно ошибка в Sun CC. Стандарт ясен, и ваше понимание этого правильно.
Кажется, это ошибка - у меня нет опыта работы с компиляторами Solaris, но все остальные компиляторы, с которыми я работал, позволят эту инициализацию.
Я бы предложил, чтобы работа над проблемой была более явной:
BBB bbb = {0, 0, 0, {0} };