0

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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
tocky
  • 107
  • 1
  • 7
  • ***std::cout << *v2 << std::endl; // print 0,but why?*** This is undefined behavior. You were unlucky that the garbage value was 0. The reason it was 0 was your OS fills each memory new memory block with zero before it gives it to your application to prevent information leakage between processes. Don't depend on this behavior. – drescherjm May 23 '22 at 12:52
  • 1
    `obj *o2 = new obj();` is value initialization. – Jason May 23 '22 at 12:53
  • 1
    Indeterminate values also contain 0. – Daniel Langr May 23 '22 at 12:53

3 Answers3

2

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.
Jason
  • 36,170
  • 5
  • 26
  • 60
  • see this ` if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;` , and if we add user constructor for `obj`, the output does not change for `obj *o2 = new obj();` – tocky May 24 '22 at 07:49
  • @tocky Does your default ctor initialize the data member `v`? If no, then the program has undefined behavior. If yes, then the program is well-formed and valid. For example, see [demo of invalid program](https://onlinegdb.com/CbsmPzkhy) and [demo of valid program](https://onlinegdb.com/Cb_gRUX12).In the demo linked above, you will find that the first demo has undefined behavior while 2nd demo is valid because its default ctor initializes `v`. Also, note that UB means anything can happen in demo1 so don't rely on its output as said in my answer also. Note the comments in the linked demos above. – Jason May 24 '22 at 08:02
  • Ok. On the other hand, if use the default constructor provided by the compiler, it is 0-valued initialization. Is this trustworthy behavior? – tocky May 24 '22 at 08:35
  • @tocky There is a subtle difference here. In case, `T` is a class type with a default constructor that is neither user-provided nor deleted, then the object is **zero-initialized**. Note zero initialization **doesn't mean** that default ctor provided by the compiler will be used(which you seem to be suggesting). But instead zero initialization here means that all non-static data members will be initialized to `0`. Note again this zero intialization of data members won't be done using the default ctor provided by the compiler. Using default ctor and zero initialization are different things. – Jason May 24 '22 at 09:04
1

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Initialization rules are a mess to remember. So lets just side step them and force the issue:

class obj
{
public:
    int v{};
};

There, now v is always going to be initialized. That even works if you add a Constructor that doesn't initialize v as then the member initialization is added automatically by the compiler.


As for why your code behaved as it did:

obj o1; 
std::cout << o1.v << std::endl; // print 32766, indeterminate values

o1 is created on the stack (or actually a register) and default initialized. Which for the int means no initialization. Whatever random data is on the stack (or in the register) is what you get.

obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?

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.

Value initialization of int sets it to 0.

int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values

Default initialization and you get random data.

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

Default initialization and you get random data. Freshly allocated memory just happens to be 0 unless it's reused by the application.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42