3

So I'm currently reading through "The C++ Programming Language" by Bjarne Stroustrup (great book), and it mentions in section 17.3.1 that an object without a defined constructor and that is initialized without an initializer, will (in non-static cases) leave built-in types undefined.

I have this code

#include <iostream>

class A {
public:
    int id;
    // No constructor defined,
    // so default constructor generated
};

void f() {
    A a; // No initializer
    std::cout << a.id << std::endl;
}

int main(int argc, char *argv[]) {
    f();
    return 0;
}

I would expect garbage to be printed when I run this code, but instead I get an initialized (0) value for a.id. Additionally, if we redefine A to be:

class A {
public:
    int id;
    A()=default;
};

Now when I run this code, a.id will be garbage values, as I had expected previously.

For the first case, why is the id member of A being initialized? Why are the two cases resulting in different results?

I am using g++/gcc version 8.1.0

  • 10
    "Undefined behaviour", like using an undefined value, means anything can happen, including boring things like getting zero. – tadman Jun 11 '18 at 22:02
  • 2
    Seeing a 0 value does not mean that `a.id` is being initialized. What you're seeing is leftover stuff; sometimes it seems to make sense, but it's garbage, nonetheless. – Pete Becker Jun 11 '18 at 22:04
  • 1
    See [what is undefined behaviour?](https://stackoverflow.com/a/4105123/1505939) – M.M Jun 11 '18 at 22:09

2 Answers2

2

but instead I get an initialized (0) value for a.id

Just because the value happens to be 0 doesn't mean it's initialized. Reading an uninitialized value is undefined behavior so the output can be anything, including 0.

If I run this same code on my system, I get the following output:

791621423
dbush
  • 205,898
  • 23
  • 218
  • 273
0

For the first case, why is the id member of A being initialized? Why are the two cases resulting in different results?

A a; // No initializer

a is uninitialized which will have indeterminate value.

As per dcl.init/12

If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced.

Using variables with indeterminate values is undefined behavior.

std::cout << a.id << std::endl; // undefined behavior for a.id

Thus, resulting to different values in different cases.

Joseph D.
  • 11,804
  • 3
  • 34
  • 67