Home > database >  the difference of automatic and dynamic variables rules in zero initialization
the difference of automatic and dynamic variables rules in zero initialization

Time:05-23

code like this,

#include <iostream>
 
class obj
{
public:
    int v;
};

int main(int argc, char *argv[])
{
    obj o1; 
    std::cout << o1.v << std::endl; // print 32766, indeterminate values
    obj *o2 = new obj();
    std::cout << o2->v << std::endl; // print 0,but why?

    int v1;
    std::cout << v1 << std::endl; // print 22024, indeterminate values
    int *v2 = new int;
    std::cout << *v2 << std::endl; // print 0,but why?
    return 0;
}

I know the global or static variables will be initialize zero.
and automatic does the indeterminate values.
but the heap object use new keyword, has any reference to explain it?

CodePudding user response:

From the C 17 Standard (11.6 Initializers)

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

For fundamental types as int it means zero-initialization.

So in this declaration

obj *o2 = new obj();

the data member v of the of the dynamically allocated object is zero-initialized.

As for this code snippet

int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?

then the object pointed to by the pointer v2 is not initialized and the next output statement can output any value that was stored in the memory extent where the new object is allocated.

CodePudding user response:

obj *o2 = new obj(); is value initialization meaning the object will be zero initialized and hence the data member v will be initialized to 0.

This can be seen from value initialization:

This is the initialization performed when an object is constructed with an empty initializer.

new T ()  (2)     

2,6) when an object with dynamic storage duration is created by a new-expression with the initializer consisting of an empty pair of parentheses or braces (since C 11);


On the other hand,

int *v2 = new int; //this uses default initialization
std::cout << *v2 << std::endl; //this is undefined behavior

the above leads to undefined behavior because you're dereferencing v2 and the allocated int object has is uninitialized and so has indeterminate value.

Undefined behavior means anything can happen. But never rely(or make conclusions based) on the output of a program that has UB. The program may just crash.

This can be seen from default initialization:

This is the initialization performed when an object is constructed with no initializer.

new T     (2)     

when an object with dynamic storage duration is created by a new-expression with no initializer;

The effects of default initialization are:

  • otherwise, no initialization is performed: the objects with automatic storage duration (and their subobjects) contain indeterminate values.

CodePudding user response:

The 1st, 3rd, 4th case are default initialization, as the effect they're initialized to indeterminate value; note that 0 belongs indeterminate value too.

The 2nd case are value initialization, as the effect the object will be zero-initialized, that means o2->v is guaranteed to be 0.

if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), 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;

On the other hand, if you change the 4th case to int *v2 = new int();, i.e. value-initialization, *v2 will be zero-initialized to 0 too.

  • Related