Memset для инициализации в С++
memset иногда используется для инициализации данных в конструкторе, как в примере ниже. Работает ли он вообще? Это хорошая идея в целом?
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};
A::A()
{
memset(this, 0, sizeof(*this));
}
Ответы
Ответ 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.)