1

Consider the following C++ code:

#include <iostream>
#include <string>

#define DUMP(_, str) do {                      \
    std::cout << str;                          \
    for (int i = 0; i < 10; ++i)               \
        std::cout << (_).x[i] << std::endl;    \
    std::cout << "a = " << (_).a << std::endl; \
    std::cout << "b = " << (_).b << std::endl; \
    std::cout << "c = " << (_).c << std::endl; \
    std::cout << "d = " << (_).d << std::endl; \
    std::cout << std::endl;                    \
} while (0)

//#define ENABLE_WTF

struct A {
    int x[10];
    float a, b, c, d;

#ifndef ENABLE_WTF
    A() : d(4) { DUMP(*this, "=== INSIDE CTOR ===\n"); }
#else
    A() : d(4) {}
#endif
};

int main() {
    A a;
    DUMP(a, "=== OUT OF CTOR ===\n");
}

As can be seen, A has a partial constructor that only initializes one of the fields, whereas all the other fields predictably remain garbage; demonstration here.

And now the question: Is it compiler-specific to zero-out the rest of A when its partial constructor has no body (demonstration here), or is that a part of C++ itself?

hidefromkgb
  • 5,834
  • 1
  • 13
  • 44
  • Can't reproduce: https://godbolt.org/z/ysUqYG – Evg Nov 20 '19 at 19:24
  • I commented/uncommented it many times with different compilers and command line options and never saw all zeros. – Evg Nov 20 '19 at 19:27
  • @Evg Hm, so it seems like the compiler I\`m currently using (ICPC 19.0) just happens to behave similarly to the one cpp.sh runs on. Mea culpa, I haven`t considered that possibility, thus wrongly deeming such behaviour universal. – hidefromkgb Nov 20 '19 at 19:33

1 Answers1

2

With the given constructor

A() : d(4) { ... }

all data member except d will be default-initialized. For built-in types this is no-op, and these data members will have indeterminate values. Reading their values is undefined behavior.

Some compilers might initialize such data members in debug builds with specific byte patterns to help catch runtime bugs.

Evg
  • 25,259
  • 5
  • 41
  • 83