5

I know that if a C++ struct is Plain Old Data ("POD") then this guarantees there is no magic in its memory structure, so it means a memcpy to an array of bytes and memcpy back is safe.

I also know that in the standard a POD struct should not have user-defined constructor. In the project I own now, there are some plain structs (with only data fields) with a default constructor defined which initializies the data members to 0. I saw other clients would use memset(&obj, 0, sizeof obj); before using the struct.

Is it ok or safe to memset the non-POD struct before I use it?

circular-ruin
  • 2,834
  • 1
  • 24
  • 30
Chen OT
  • 3,486
  • 2
  • 24
  • 46

2 Answers2

3

Having a constructor does not make a struct non-POD.

An aggregate class is called a POD if it has no user-defined copy-assignment operator and destructor and none of its nonstatic members is a non-POD class, array of non-POD, or a reference.

Given that, it is perfectly safe to call

memset(&obj, 0, sizeof obj);

on an object of a struct that has a constructor as long as it is a POD.

Whether it is OK or not, depends. If the default constructor of the struct wants a member to be initialized to 1 for sane behavior, the above call to memset may impact the behavior of code that depends on 1 being the default value.

Take the example of the following struct:

struct Direction
{
   Direction() : x(1.0), y(0.0), z(0.0) {}
   double x;
   double y;
   double z;
};

An object of type Direction expects that at least of one of the components will be non-zero. You can't define a direction when all the components are zero. If you use memset to set everything to 0, code will likely break.

EDIT It appears, from the comments below, as though the definition of a POD has changed from C++03 to C++11.

Using memset(&obj, 0, sizeof obj); may not be safe after all.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    But I saw the SO post http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special#4178176 says "An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1)" And I look up the standard `n3242.pdf` page 203, it also describes the same paragraph. It looks the Aggregates can only have default constructor generated by compiler. – Chen OT Apr 17 '14 at 03:28
  • @ChenOT if you follow that link a little bit down, it goes to describe POD structs. – R Sahu Apr 17 '14 at 03:37
  • 1
    I've read the following part of that post. What I understand is if the type is not even a aggregate, it is not a POD. And the type with a user-declared constructor cannot be a aggregate. – Chen OT Apr 17 '14 at 04:02
  • @ChenOT that's not how I interpreted the language. – R Sahu Apr 17 '14 at 04:12
  • 9.10: "A POD struct is a non-union class that is both a trivial class and..."; 9.6: "A trivial class is a class that has a default constructor (12.1), has ***no non-trivial default constructors***..."; 12.1/4: "A default constructor is trivial if it is ***not user-provided*** and...". – Tony Delroy Apr 17 '14 at 05:01
  • @TonyD, that makes sense. What do you make of the paragraph that quoted from that answer? Was that a wrong interpretation on the part of the author? – R Sahu Apr 17 '14 at 07:02
  • 2
    @RSahu The answer you've quoted says it's based on "C++ standard (C++03 9 §4)" - I'm quoting C++11, final draft. Things may have changed. More generally, the question is about knowing two things: 1) if `memcpy` is safe - that is much better asserted at compile time with [is_trivially_copiable](http://en.cppreference.com/w/cpp/types/is_trivially_copyable) than deduced once by the programmer and hoping maintenance programming won't break it, and 2) if `memset()` is safe: I doubt if it is portably even for POD - e.g. all 0 bits might not be valid for some weird `float`/`double` representation. – Tony Delroy Apr 17 '14 at 07:43
  • 2
    @TonyD: Indeed, it's important to differentiate `memcpy` and `memset`! – Matthieu M. Apr 17 '14 at 07:45
0

IMO this depends on the use case. I have seen memset used to set the data with white space character on few mainframe appications i.e

memset(&obj, ' ', sizeof(obj));

In case the struct defines a const variable and initializes the value, memset would override such value. So it depends and most cases safe to use memset to initialize for PODS. thats my 2 cents.