Вопрос

I am using memset this way:

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

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

Should I use this way? Why and Why not? Is there a better way? Need some guidance..

Это было полезно?

Решение

This is generally a bad idea.

If someone adds a new member to the class it could break horribly if the type of the new member has a proper constructor and memset is not suitable.

Formally, according to the standard your user-defined constructor means that A is not a POD type (or trivially-copyable type in C++11) and so it is not safe to use memset or memcpy on it.

There are several ways to do this safely:

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

Alternatively, do not add a constructor and value-initialize instances of the type:

A a = A();

Or, group the POD members together and value-initialize them all at once in the constructor:

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

A::A() : data()
{ }

In general it's better to use value-initialization in C++ and rely on the compiler to do the equivalent of the memset (or calling default constructors) rather than expicitly using memset yourself. The code will be less fragile and easier to maintain.

Другие советы

You might get away with it for now. Even though your class is NOT a POD (it has a custom constructor), in practice most implementation will do 'the right thing TM' as long as you don't inherit from your class. So better don't do it. Beware though, all bits zero is not guaranteed to be either NULL-pointer nor a floating point 0.0 .

If you want a initialised POD, just define the variable thus:

POD_T my_var = {};

C++ will automatically use the most efficient initialisation possible.

If you don't want a POD, use the initialiser list of your constructors, and let the compiler optimize for you.

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

This one and in general regarding the C++ object memory model has been explained nicely in the book "Inside the c++ object model" by Stanley B. Lippman.

Use of both memcpy() and memset(), however, works only if the classes do not contain any compiler generated internal members. And C++ object model has not been defined by standard so different compiler is free to implement and hence we can never rely 100% that whether compiler has generated/inserted internal members(VPTR is most common) or not.

He has explained it using the class which has member of virtual function type(for such classes compiler insert VPTR ).

A::A()
{
    // vptr must be set before user code executes
    __vptr__A = __vtbl__A;
    // oops: memset zeros out value of vptr
    memset( this, 0, sizeof(A));
};

Hence this is not the good idea even though it could be more efficient in certain scenario.

Try following code

memset(this, 0, sizeof(A));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top