в C ++ 11, вы всегда можете (безопасно) заменить инициализацию memset () пустым инициализатором?

Я часто сталкиваюсь с POD-структурами в коде, которые вручную инициализируются нулями memset вот так:

struct foo;
memset(&foo, 0, sizeof(foo));

Я проверил стандарт C ++ 11 и он говорит: «Объект, инициализатором которого является пустой набор скобок, то есть (), должен быть инициализирован значением». С последующим: «Инициализировать значение [структура pod] типа T означает … объект инициализируется нулями».

Итак … это значит, что вы можете всегда безопасно сжать приведенный выше код до следующего:

struct foo{};

И иметь гарантированно инициализированную структуру, как если бы вы вызвали memset(&foo, 0, ...)?


Если так, тогда, вообще говоря, вы можете безопасно инициализировать что-нибудь с пустыми инициализаторами вот так:

SomeUnknownType foo{};  // will 'foo' be completely "set" to known values?

Я знаю, что это не всегда возможно в C ++ 03 (раньше единый синтаксис инициализации) но возможно ли это сейчас в C ++ 11 для любого типа?

9

Решение

Вы можете, конечно, инициализировать любой стандартный тип макета, используя пустые скобки, и получить его инициализированным нулем. К сожалению, после добавления конструкторов в изображение это не обязательно так:

struct foo {
int f;
};
struct bar {
int b;
bar() {}
};

foo f{};
bar b{};

В то время как f.f инициализируется нулем, b.b неинициализирован. Однако с этим ничего не поделаешь bar потому что ты не можешь memset() это тоже. Это должно быть исправлено.

10

Другие решения

Memset инициализирует его до 0, но пустые скобки будут означать инициализацию вашего объекта (есть разница).

Цитирование из стандарта:

Инициализировать значение объекта типа T означает:

  • если T является типом класса с конструктором, объявленным пользователем, то вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);

Кроме того, делая struct foo{}; безопасен и заботится о том, чтобы не сбрасывать указатель виртуальной таблицы.

Но делать memset(&foo, 0, sizeof(foo)); В случае виртуальных функций это действительно очень плохо, так как он сбрасывает указатель на виртуальную таблицу.

3

По вопросам рекламы [email protected]