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

Memset для инициализации в С++

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

class A {
public:
   A();
private:
   int a;
   float f;
   char str[35];
   long *lp;
};

A::A()
{
   memset(this, 0, sizeof(*this));
}
4b9b3361

Ответ 1

Не используйте memset. Это переживание C и не будет работать на не-POD. В частности, использование его в производном классе, который содержит любые виртуальные функции, или любой класс, содержащий нестроенный, приведет к катастрофе.

С++ предоставляет специальный синтаксис для инициализации:

class A {
public:
   A();
private:
   int a;
   float f;
   char str[35];
   long *lp;
};

A::A()
    : a(0), f(0), str(), lp(NULL)
{
}

Честно говоря, я не уверен, но memset также может быть плохой идеей о плавающих запятых, так как их формат не указан.

Ответ 2

Это ужасная идея. Вы просто перебираете данные, не обращая внимания на то, как объекты должны быть инициализированы. Если ваш класс является виртуальным, вы также можете уничтожить указатель vtable.

memset работает с необработанными данными, но С++ не связан с необработанными данными. С++ создает абстракции, поэтому, если вы хотите быть в безопасности, вы используете эти абстракции. Используйте список инициализаторов для инициализации членов.

Вы можете сделать это для типов POD:

struct nothing_fancy_here
{
    bool b;
    int i;
    void* p;
};

nothing_fancy_here x;
memset(&x, 0, sizeof(x));

Но если вы делаете это на this, это означает, что вы находитесь в определяемом пользователем конструкторе и больше не считаетесь типом POD. (Хотя, если все ваши члены POD могут работать, поскольку ни один из них не содержит 0 в качестве значения ловушки. Я уверен, что не уверен, что здесь появляются какие-либо другие источники поведения undefined.)