Скажем, у меня есть следующее описание структуры (простая структура без конструктора).
struct Foo
{
int x;
int y;
int z;
char szData[DATA_SIZE];
};
Теперь скажем, эта структура является членом класса C++ следующим образом:
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 к списку инициализации конструктора без параметров следующим образом:
CFoobar::CFoobar()
: _foo()
{
То, что это, кажется, обнуляет членские переменные _foo. По крайней мере, это имело место с g ++ на Linux.
Теперь вот мой вопрос: Этот стандартный C++ или является этим компилятором определенное поведение?
Если это - стандартное поведение, кто-то может заключить мне в кавычки ссылку из официального источника? Какие-либо "глюки" в отношении неявного нулевого-init поведения с более сложными структурами и классами?
Да, это определенное поведение в соответствии со стандартом. 12.6.2 [class.base.init] / 3: "если список-выражений mem-initializer опущен, то базовый класс или подобъект-член имеет значение -initialized . "
Однако будьте осторожны, если Foo
не был POD-типом, но все еще не имел конструктора, объявленного пользователем (например, у него был std :: string
type), то некоторые очень популярные компиляторы неправильно инициализируют значение его.
Все известные мне компиляторы правильно выполняют инициализацию значений членов POD, когда вы используете ()
в качестве инициализатора в списке инициализаторов конструктора.
Это эквивалент float foo = float();
Он обнульет объект, даже если представление значения не является all-bits-zero. Т.е. это даже лучше, чем memset()
.
Мне трудно читать стандарт, но я нашел его, думаю:
Инициализировать объект типа T по значению означает:
если T - тип класса, не являющийся объединением, без конструктора, объявленного пользователем, то каждый нестатический член данных и базовый компонент класса T - инициализируется значением Инициализация значения для такого объекта класса может быть реализована путем инициализации объекта нулем и последующего вызова конструктора по умолчанию.
Раздел 8.5