1

The following C++20 program is accepted without any warning in all compiles I have tried:

struct A { const int & x = z; int y = x; int z; };

int main()
{
    return A{.z=3}.y;
}

https://gcc.godbolt.org/z/nqb95zb7c

But every program returns some arbitrary value. Is it right to assume that this is undefined behavior?

  • 1
    `y = x`, so `y = z` reads `z` before it is initialized. – Jarod42 Jul 21 '21 at 11:48
  • GCC points out @Jarod42 comment and clang bails with no code - live - https://godbolt.org/z/3fxKhrKnb – Richard Critten Jul 21 '21 at 11:49
  • 1
    You can also use constant evaluation to catch undefined behaviour: https://godbolt.org/z/WYv1W8PcW (which makes gcc point out the uninitialised access) – Artyer Jul 21 '21 at 12:31
  • *it right to assume that this is undefined behavior?* Yes, because reading an uninitialized variable is **undefined behavior**. Could be an arbitrary value, could crash, could awaken Cthulhu from his slumber, or worse... could appear to work as expected. – Eljay Jul 21 '21 at 12:47

1 Answers1

6

Members are initialized in the order they appear in the class definition, hence the designated initializer is not that relevant, and also this

struct A { 
    const int & x = z; 
    int y = x;           // <- read of indeterminate value !
    int z = 42;          // <- doesn't really matter because y is initialized before ! 
};

int main() {
    return A{}.y;
}

is undefined for the same reason.


See also the example from cppreference:

struct A {
  string str;
  int n = 42;
  int m = -1;
};
A{.m=21}  // Initializes str with {}, which calls the default constructor
          // then initializes n with = 42
          // then initializes m with = 21

The example is actually to illustrate something else, but it also shows how members are initialized in order.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185