C ++ инициализация пустого члена - обнуляет память? - PullRequest
3 голосов
/ 09 апреля 2009

Я изначально написал такой код:

class Foo
{
public:
  Foo() : m_buffer()
    {}

private:
  char   m_buffer[1024];
};

Кто-то, кто умнее меня, сказал, что наличие инициализатора m_buffer () обнулит память. Я хотел оставить память неинициализированной. У меня не было времени, чтобы обсудить это дальше, но это пробудило мое любопытство.

Раньше я думал, что было бы разумно всегда перечислять каждого члена в списке инициализатора.

Может ли кто-нибудь описать это поведение дальше?

1) Почему пустой инициализатор заполняет память?

2) Действительно ли это только для типов данных POD? Я слышал, что это так, но у меня нет стандартного подручного.

Спасибо

Ответы [ 2 ]

11 голосов
/ 09 апреля 2009

Если у вас есть такой инициализированный член, это будет value-initialized. Это также верно для POD. Для структуры каждый член инициализируется значением таким образом, а для массива каждый его элемент инициализируется значением.

Инициализация значения для скалярного типа, такого как указатель или целое число, он будет инициализирован до 0, преобразованного в правильный тип. Таким образом, вы получите нулевые указатели или false или любой другой тип, который у вас есть конкретно.

Обратите внимание, что правило слегка изменилось с C ++ 98 на C ++ 03 (что мы имеем сейчас), что может иметь неожиданные последствия. В C ++ 98 этого не было value-initialization. Он сказал, что инициализация по умолчанию происходит, что для не POD-типа всегда означало, что вызывается конструктор по умолчанию. Но value-initialization в C ++ 03 имеет особое значение, если нет объявленного пользователем конструктора: тогда каждый элемент инициализируется значением.

Вот разница:

struct A { int c; ~A() { } }; // non-POD, but no user declared ctor
struct B { A a; B():a(){ } } b;

Теперь в C ++ 03 вам будет гарантировано, что b.a.c равно нулю. В то время как в C ++ 98 b.a.c будет иметь неопределенное значение.

1 голос
/ 09 апреля 2009

Раньше я думал, что это мудро всегда перечислять каждого члена в список инициализаторов.

Это необходимо для инициализации всех членов.

Чтобы решить вашу задачу, просто удалите m_buffer из списка инициализаторов.

template <typename T>
struct C
{
    C():
        buff(),
        var(),
        object()
    {
    }
    T buff[128];
    T var;
    std::string object;
};

Независимо от того, какой тип T использует T (), используйте конструктор по умолчанию. Для int, chars и т. Д. Это 0, для массивов - {T ()}. А для классов это просто конструктор по умолчанию.

...