Search code examples
c++initializationdata-members

Initial data member values


I was very surprized to see that in the version of Visual C++ that comes with VS2013 the data members of a newly created class seem to be automatically initialized to 0 or null depending on their type. This is new - and very useful! - behaviour in my experience. I have previously only used VC++ Version 4 when writing serious apps and way back in the middle 1990's the initial values were explicitly stated as being undefined/random.

Is this perhaps some helpful attribute of using the debug libraries, or is it possible to rely on null initialization all the time?

As requested, some example code - nothing very exciting I am afraid:

class CData
{
public:
    CData();
    CData(const CData &copy);
    ~Data();
    const CData& operator=(const CData &copy);
    //Accessors/Mutators follow...


private:
    bool Initialize_Data();
    //Just giving a couple of examples of data member sets.
    char *input_script_name;
    int size_input_script_name;
    int size_input_script_name_buffer;
    char *interpreter_name;
    int size_interpreter_name;
    int size_interpreter_name_buffer;
};

CData::CData()
{
    Initialize_Data();
}

CData::~CData()
{
    //Code to store relevent data in registry
    //and then free dynamically allocated memory follows...
}

bool CData::Initialize_Data()
{
    //Code to retrieve data from registry stored at end of last run follows
    //along with routines to check bounds.
    //
    //At this point, without executing any further a breakpoint is triggered
    //and on inspecting data members in a Watch on 'this' I find them
    //to be already initialized to either 0 or null respectively.

}

...

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //Application entry point;

   CData application_data;  //and away it goes!

   //Usual name mutex to prevent multiple instances and message loop follow...
}

As I said VERY basic and I am not illustrating all the code. However, at the point the breakpoint in 'Initialize_Data' is reached - which is immediately on creating the class and BEFORE anything else is executed - all the data members show up as either 0 or null in a Watch. Which is rather surprising!


Solution

  • This is just a coincidence. What you probably observe is that something clears a lot of memory just before your object is initialized, and then your object is placed in that zero-initialized memory. There is no guarantee that this will remain the case, nor will you be able to rely on this on other platforms/compilers. In Debug mode, Visual C++ actually tries to clear to a non-zero bit-pattern, for example.

    If you want to zero initialize, you can use the C++ 11 non-static member initializers like this:

    char *input_script_name = nullptr;
    int size_input_script_name = 0;
    int size_input_script_name_buffer = 0;
    char *interpreter_name = nullptr;
    int size_interpreter_name = 0;
    int size_interpreter_name_buffer = 0;
    

    I'm not sure if the current compilers optimize this to a memset if everything is set to 0, but this is the way to go if you have access to a C++11 compiler.

    Update

    Just checked with Clang 3.4, it does emit a memset if everything is set to 0. GCC initializes using registers, but I suspect that's because my small test case only had ~10 member variables.