Подтвердить что ты не робот

Может ли структура-член быть нуль-init из списка инициализатора конструктора без вызова memset?

Скажем, у меня есть следующее объявление структуры (простая структура без конструктора).

struct Foo
{
    int x;
    int y;
    int z;
    char szData[DATA_SIZE];
};

Теперь скажем, что эта структура является членом класса С++ следующим образом:

class CFoobar
{
     Foo _foo;
public:
     CFoobar();
};

Если я объявляю конструктор CFoobar следующим образом:

CFoobar::CFoobar()
{
    printf("_foo = {%d, %d, %d}\n", _foo.x, _foo.y,_foo.z);
    for (int x = 0; x < 100; x++)
       printf("%d\n", _foo.szData[x]);
}

Как и следовало ожидать, когда запускается CFoobar-конструктор, данные об мусоре распечатываются. Очевидно, что легкое исправление касается memset или ZeroMemory & _foo. Это то, что я всегда делал...

Однако я заметил, что если добавить _foo в список инициализации конструктора без параметров:

CFoobar::CFoobar()
: _foo()
{

Это означает, что это нулевые переменные-члены _foo. По крайней мере, это было в случае с g++ на linux.

Теперь вот мой вопрос: Является ли это стандартным С++ или это специфическое поведение для компилятора?

Если это стандартное поведение, может ли кто-нибудь указать мне ссылку из официального источника? Любые "gotchas" в отношении неявного поведения с нулевым init с более сложными структурами и классами?

4b9b3361

Ответ 1

Да, это определено поведение в соответствии со стандартом. 12.6.2 [class.base.init]/3: "если список выражений mem-инициализатора опущен, базовый класс или подобъект-член инициализируется инициализацией значения."

Будем предупреждать, однако, если Foo не был POD-типом, но все еще не имел конструктора, объявленного пользователем (например, у него был тип std::string), то некоторые очень популярные компиляторы не могли бы правильно инициализировать его значение.

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

Ответ 2

Мне трудно читать стандарт, но я нашел его, я думаю:

Для инициализации объекта типа типа T:
если T - тип неединичного класса без конструктора, объявленного пользователем, то каждый нестатический элемент данных и базовый элемент, класс компонента T инициализируется значением Инициализация значений для такого объекта класса может быть реализована путем нулевой инициализации объекта, а затем вызова конструктора по умолчанию.

Раздел 8.5

Ответ 3

Это эквивалент float foo = float();

Он будет обнулять объект, даже если представление значения не является битом-нолем. То есть это даже лучше, чем memset().