Zero-initializing an array data member in a constructor

Just use value initialization in the constructor initialization list. That is the idiomatic way of doing this in C++.

Cache::Cache() : byte()
{ 
}

Note that C++11 allows this syntax too:

Cache::Cache() : byte{}
{ 
}

In case you're wondering why this works, from the C++ 11 standard (note this also applies to C++03):

C++11 § 8.5,p10

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

That term value-initialized takes us to:

C++11 § 8.5,p7

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type9 with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

  • if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.

  • if T is an array type, then each element is value-initialized;

  • otherwise, the object is zero-initialized.

The third option in this trips the value-initialization of each element; the fourth applies once we get to each of those elements because they're (a) no class types, so (1) and (2) are gone, and (b) not arrays, so (3) is gone. That leaves only the last one, and your elements are zero-initialized.


In Cache constructor, when you do :

byte[16]={0};

You are only setting the 16th byte of your array (which is out of bounds, so this operation has undefined behavior). Array objects are default-initialized in C++, because you store int, no initialization is performed.

You can use std::fill to initialize it :

Cache::Cache()  
{
  std::fill(byte, byte+16, 0);
}

Or you can use a regular for-loop over your array.


You are doing it wrong on many levels. The syntax you use does not do what you think it does. What you are doing now is essentially initializing 17th element of the table to 0.

In your case memset is probably the fastest and simplest. However, it would not work for complex types, so I would consider writing a simple snippet for general case like:

template<typename T>
inline void zero_init(T array[], size_t elements){
 if( std::is_pod<T>() ) memset(array, 0, sizeof(T)*elements);
 else std::fill(begin(array), begin(array)+elements, 0);
}

This will check if the type is a POD-type, which in this context means it can be initialized via memset and will put 0 for the whole table. If the T does not support it, then for each element an equivalent of element = 0 will be called. Also the check is possible to be evaluated at the compile time, so most probably the if will be compiled away and a simple "one-liner" version will be created for each type at the compilation time.

You can call it via:

Cache::Cache()  
{
  zero_init(byte, 16);
}