7

I found this piece of C++ code that uses memset() to initialize an object:

struct Message
{
   Message()
   {
      memset(this, 0, sizeof(Message));
   }

   unsigned int a, b, c;
};

Since this is a POD structure, this code should be fine.
Is there any advantage in using memset instead of a constructor such as:

Message() : a(0), b(0), c(0) {}
10
  • 5
    Consider what happens if your object has virtual table pointer. Good compiler will most probably determine that you have POD and memset them or something like this in second case. But if will decide later to build a hierarchy, you done goofed. Commented Mar 2, 2015 at 11:04
  • 8
    At least insert a static_assert right before/after the memset. This tells both the human reader as well as the compiler that you assume Message to be a POD; the compiler will fail if it isn't, and the reader will know why you think memset would be ok. Commented Mar 2, 2015 at 11:11
  • 5
    I highly doubt it, memset should enforce a call to memory, which won't be optimized out, as it will be considered having side effects. Declaring initial values statically gives more options for compiler to optimize. Commented Mar 2, 2015 at 11:15
  • 4
    @leemes: Then I'd settle with: static_assert(std::is_standard_layout<Message::value, "class is not memsettable") Commented Mar 2, 2015 at 11:17
  • 2
    Another note: POD types can be zero-initialized with value-initialization (empty paranthesis) like Message x = Message();, however, this doesn't prevent Message x; to be written, in which case it is uninitialized. But that's simply how PODs work... Commented Mar 2, 2015 at 11:20

3 Answers 3

6

There is no advantage in using memset() like this. Leaving behind all the obvious disadvantages and future pain, there is one disadvantage that makes it less efficient than

Message() : a(0), b(0), c(0) {}

This is because PODs are usually stored in arrays. So good (smart) compiler will have an advantage to replace initialization of multiple objects in an array with a single memset(), in case of

Message * messages_1 = new Message[100];

Or

std::vector<Message> messages_2;
messages_2.resize(100);

Even when only single object is being constructed, good compiler will use memset(), behind the curtain.

Sign up to request clarification or add additional context in comments.

1 Comment

The memset approach does have one advantage for having deterministic 0-values in the padding bytes. Sometimes that matters, perhaps for a hash function that reads it as a blob of data, rather than as an object.
5

Note that in C++11 and newer you have a nicer option than either of those:

struct Message
{
   unsigned int a = 0;
   unsigned int b = 0;
   unsigned int c = 0;
};

This should produce identical code (and optimisation opportunities) to the constructor-with-initialisation-list approach while:

  • Using less code.
  • Being more readable.
  • Removing the need to worry about updating initialisation list when members are added.
  • Removing the need to think about what to do if b needs to default to -1 later.

Comments

1

The "memset approach" has two advantages over initializers for structures which are large but simple collections of data: It is clearer and has better maintainability.

  • Clearer because it is obvious and easily verifiable what happens. With single initializations, a reviewer must verify that no member is omitted. (A good compiler called with a sufficiently high warning setting will warn, but in a large project warnings easily drown in the noise.)
  • Better to maintain because the code stays correct even if a member is added.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.