11

I frequently come across POD structs in code that are manually zero-initialized with memset like so:

struct foo;
memset(&foo, 0, sizeof(foo));

I checked the C++11 standard and it says: "An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized." Followed by: "To value-initialize a [pod struct] of type T means ... the object is zero-initialized."

So... does this mean you can always safely condense the above code to just the following:

struct foo{};

And have a guaranteed initialized struct as if you had called memset(&foo, 0, ...)?


If so, then generally speaking, can you safely initialize anything with empty initializers like so:

SomeUnknownType foo{};  // will 'foo' be completely "set" to known values?

I know this wasn't always possible in C++03 (before uniform initialization syntax) but is it possible now in C++11 for any type?

MikeTusar
  • 655
  • 6
  • 10
  • 2
    check this thread : http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a-difference-with-new General answer is yes. – CS Pei Aug 17 '13 at 02:36
  • 1
    Be aware that MSVC has never properly supported value initialization and will fail in some contexts. [Microsoft does not seem to be interested in fixing the bug](http://connect.microsoft.com/VisualStudio/feedback/details/484295). – Casey Aug 17 '13 at 04:23
  • @Casey: That's a pretty serious bug, I wonder if it's been fixed in the latest VS. Fortunately, I use gcc and clang (which seem to care about being standards compliant) and my code does **not** have to be portable to other compilers or even older versions of gcc or clang. – MikeTusar Aug 17 '13 at 04:37
  • Also see: http://stackoverflow.com/a/38103250/3223828 – Stuart Gillibrand Jun 29 '16 at 18:17

2 Answers2

10

You can certainly initialize any standard layout type using empty parenthesis and get it zero initialized. Once you add constructors into the picture, this isn't necessarily true, unfortunately:

struct foo {
    int f;
};
struct bar {
    int b;
    bar() {}
};

foo f{};
bar b{};

While f.f is zero initialized, b.b is uninitialized. However, there isn't anything you can do about bar because you can't memset() it either. It needs to be fixed.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 1
    So to summarize, wherever `memset()` can safely be used to initialize a type, so can the empty initializer (parentheses/braces) to achieve zero-initialization of the memory ... correct? – etherice Aug 17 '13 at 02:51
  • 1
    @etherice: Correct. `memset()` can only be used on PODs and PODs are always zero-initialized. That said, this applies to all members. I don't think the empty parenthesis/braces make any guarantee about padding. It shouldn't matter but sometimes it does. – Dietmar Kühl Aug 17 '13 at 02:56
  • They made `{}` be aggregate initialization instead of value initializatio for an aggregate struct. Zero initialization and hence for aggregates value initialization guarantees that padding is zero. But I don't believe that aggregate initialization does. – Johannes Schaub - litb Aug 17 '13 at 13:35
4

Memset will initialize it to 0 but empty parenthesis will value initialze your object(there is a difference).

Quoting from the standard:

To value-initialize an object of type T means:

  • if T is a class type with a user-declared constructor, then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

Also, doing struct foo{}; is safe and it takes care of not reseting the virtual table pointer.

But doing memset(&foo, 0, sizeof(foo)); in case of virtual functions is really really bad as it resets the pointer to the virtual table.

Saksham
  • 9,037
  • 7
  • 45
  • 73
  • 1
    If there is `virtual` function in `foo` using `memset()` on an object results in undefined behavior. You can only `memset()` certain types. They used to be called PODs (plain old data) but I think they are called something different in C++11. – Dietmar Kühl Aug 17 '13 at 02:37
  • @DietmarKühl Thanks for the useful info. Just started learning. Any other useful comments for my answer would be very helpful. – Saksham Aug 17 '13 at 02:37
  • @DietmarKühl, C++11 still uses POD, unless the meaning changed and it's another term you're thinking of for what used to be a POD. – chris Aug 17 '13 at 02:45
  • 1
    @DietmarKühl: There is still POD, but the C++11 standard further-divides POD concept into sub-concepts `standard-layout` and `trivial-type` (POD is both). – etherice Aug 17 '13 at 02:48
  • 1
    @chris: Right, I just checked: POD gets defined. For many of the interesting uses the term got generalized to, I think, _standard layout types_ but these can't be initialized with `memset()` in general (only the POD subset can). – Dietmar Kühl Aug 17 '13 at 02:48
  • @chris can you please or someone else please highlight on the vtable part in my answer. Is it right or not?? – Saksham Aug 17 '13 at 02:49
  • @Saksham: It is correct. You can only safely `memset` types that qualify as `standard-layout` (see http://en.cppreference.com/w/cpp/concept/PODType which mentions it). Polymorphic types are especially unsafe due to the vpointer(s) in the object's layout. – etherice Aug 17 '13 at 02:58
  • @Saksham: You got one ;) – MikeTusar Aug 17 '13 at 05:06