1

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..

lakshmen
  • 28,346
  • 66
  • 178
  • 276
  • Um, Is `class A` POD? I don't know detail of standard, but I guess it is. – ikh Mar 25 '14 at 11:20
  • No, that doesn't make any sense. What are you trying to do? – bosnjak Mar 25 '14 at 11:20
  • 6
    You'll get away with it. That kind of luck runs out later, when a hapless maintainer loses a day of his life trying to figure out why his method call to an added virtual method bombs. Doing this correctly doesn't cost you anything. – Hans Passant Mar 25 '14 at 11:22
  • @Lawrence Why doesn't that make sense? It looks like it's intended to set `a`, `f`, `str[0...34]` and `lp` all to zero. Strictly speaking, that's not guaranteed to work for `f` and `lp`, but likely to work on many implementations. –  Mar 25 '14 at 11:22
  • @hvd: if you look it like that.. but still, not something I would recommend using. – bosnjak Mar 25 '14 at 11:24
  • @ikh, `A` is not a POD because it has a user-defined constructor – Jonathan Wakely Mar 25 '14 at 11:27
  • 1
    Every time in the future when you add a new variable to this class you will need to be careful that the ctor doesn't break something. That is not a good design. Just use the normal way that C++ initializes its instance variables. – AndersK Mar 25 '14 at 11:37
  • Exact duplicate of [memset for initialization in C++](http://stackoverflow.com/questions/2481654/memset-for-initialization-in-c) – YSC Feb 08 '17 at 12:48
  • That looks like the way we used to write Borland C++ code in 1992... ;-) probably not a good idea these days... – Bimo Jul 24 '18 at 00:23

4 Answers4

9

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.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
2

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() { }
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
1

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.

Mantosh Kumar
  • 5,659
  • 3
  • 24
  • 48
-1

Try following code

memset(this, 0, sizeof(A));
Elixir Techne
  • 1,848
  • 15
  • 20