Search code examples
c++c++14zero-initialization

C++ Zero-Initialization


I'm having trouble understanding when and why exactly a member in my class is zero-initialized according to http://en.cppreference.com/w/cpp/language/zero_initialization.

Consider the following test program:

#include <iostream>
#include <stdio.h>

class MyTest {
private:
    const static unsigned int dimension = 8;
    void (* myFunctions [dimension])();

public: 
    MyTest() {}

    void print() { 
        for(unsigned int i=0; i < MyTest::dimension; i++) {
            printf("myFunctions[%d] = %p\n", i, this->myFunctions[i]);
        }   
    }
};


int main() {
    //We declare and initialize an object on the stack 
    MyTest testObj = {};
    testObj.print();

    return 0;
}

I am declaring a class to have an array of 8 function pointers of the signature "void functionname()". When I declare and initialize an object of the class in main as MyTest testObj = {}; or MyTest testObj;, I expected it to be zero-initialized, i.e. all pointers are null pointers.

However, compiling with g++ 5.3.0 on my Windows 10 machine with g++ -m32 -o test -std=c++14 test.cpp && test machine gives the output:

myFunctions[0] = 76dd6b7d
myFunctions[1] = 00401950
myFunctions[2] = 0061ff94
myFunctions[3] = 004019ab
myFunctions[4] = 00401950
myFunctions[5] = 00000000
myFunctions[6] = 003cf000
myFunctions[7] = 00400080

Which look like un-initialized values from the stack..

If I move the declaration of the object outside of main (as a global variable), it prints all zeroes again.

If I have understood cppreference correctly, this is because I have a variariable with static storage duration, and is thus zero-initialized. It initializes my class type by zero-initializing all non-static data members of my class (i.e., the myFunctions) array. An array is initialized by zero-initializing every element of it, which, in my function pointer case, is a null pointer.

Why does it not zero-initialize my object the stack when I declare it with MyTest testObj = {};?


Solution

  • The following

    MyTest testObj = {};
    

    is not zero-initialization for MyTest, but is simply calling its default constructor. The cppreference page explains why (emphasis mine):

    As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.

    MyTest is a class type, and a has a constructor.


    Defining the constructor with

    MyTest() = default;
    

    will instead zero-initialize the object.

    Relevant Standard quotes (emphasis mine) below.

    From [dcl.init#8]:

    To value-initialize an object of type T means:

    • if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;

    • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

    • ...

    From [dcl.init.list]:

    List-initialization of an object or reference of type T is defined as follows:

    • ...

    • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.