0

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!

  • 8
    You cannot rely on zero-initialization unless the standard says so. This is most likely a feature of your implementation. To know whether the standard gives you 0 initialization, you would have to post a relevant and complete code sample. – juanchopanza Aug 08 '14 at 08:32
  • 1
    Sometimes memory is zero initialised when run in debug under VS but this is compiler dependent and should not be relied, you'd have to post your code still – EdChum Aug 08 '14 at 08:35
  • Also see [**zero initialization**](http://en.cppreference.com/w/cpp/language/zero_initialization). – juanchopanza Aug 08 '14 at 08:36
  • 2
    Can you post some example code? There are occasions when data members will be zero initialised. In my experience the debug VC libraries use bit patterns to fill at least some areas of memory that should be unitialised by the standard. – Andy Brown Aug 08 '14 at 08:39
  • Sure thing. I have added some code snippets to show how simple my current classes are which give me zero-intialized data members. –  Aug 08 '14 at 09:00

1 Answers1

0

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.

Anteru
  • 19,042
  • 12
  • 77
  • 121
  • Fascinating! I had not thought of that situation of memory recently freed and so forth. I think you are probably right that is what is going on. –  Aug 08 '14 at 09:08
  • @juanchopanza Writing ``CData application_data{};`` is merely equivalent to calling the default constructor, but it does not force zero initialization. – Anteru Aug 08 '14 at 09:15
  • @juanchopanza No, it doesn't, if you have a default constructor specified as the OP has. See: http://pastie.org/9455280 Nothing is initialized. If you remove the default constructor, then yes, it gets zero-initialized. – Anteru Aug 08 '14 at 09:22
  • @Anteru You're right, I had missed OP's patholigical default constructor. – juanchopanza Aug 08 '14 at 09:32
  • Pathological? Could you tell me why its pathological to have a default constructor? When I was learning C++ it was pretty much compulsory to write a default constructor and if your class used dynamically allocated memory then I was taught to also write a copy constructor and assignment operator to allow deep copying. Have these guidelines changed? Admittedly I did learn in 1996, so.., it wouldn't be too surprising! –  Aug 08 '14 at 16:07
  • Also - just tried out that initialization inside the class declaration, and it WORKS!!! VERY, very cool!!! C++ has needed that since the beginning. I guess it is another new - to me! - feature? –  Aug 08 '14 at 16:19
  • This is new with C++11. – Anteru Aug 08 '14 at 19:18