Why does member `float x` get initialized with `0.` for the objects `a` and `b` in main()? [duplicate]

StackOverflow https://stackoverflow.com/questions/20767342

  •  21-09-2022
  •  | 
  •  

Вопрос

Could somebody indicate which clause in the Standard supports the following behavior obtained in Coliru, for the snippet:

#include <iostream>

class A
{
    int i;
    float x;

    public:
    A() : i(10) {}
    A(int i) : i(i) {}
    int GetI() { return i; }
    float GetF() { return x; }
};


int main()
{
    A a;
    A b(1);
    A x{};
    A y{1};
    std::cout << a.GetI() << '\n';
    std::cout << a.GetF() << '\n';
    std::cout << b.GetI() << '\n';
    std::cout << b.GetF() << '\n';
    std::cout << x.GetI() << '\n';
    std::cout << x.GetF() << '\n';
    std::cout << y.GetI() << '\n';
    std::cout << y.GetF() << '\n';
}

The code prints:

10
0 <-- Shouldn't be unknown?
1
0 <-- idem
10
0
1
0

Edit:

This paragraph was obtained from the TCPL 4th edition, page 490:

For this, the rules are not as clean as we might like. For statically allocated objects (§6.4.2), the rules are exactly as if you had used {}, so the value of alpha is {"","",0}. However, for local variables and free-store objects, the default initialization is done only for members of class type, and members of built-in type are left uninitialized, so the value of beta is {"","",unknown}.

Mr. Stroustrup doesn't say anything about undefined behavior.

Это было полезно?

Решение

0 is one of the possible arbitrary value an uninitialized variable can acquire: the program has undefined behavior. Given that there is a fair chance that memory starts off zero initialized, 0 is a likely outcome: the IEEE 754 representation for 0 happens to be all zeros. There is, however, no guarantee that the value will be 0.

Другие советы

At Mat pointed out, reading an uninitialized variable in C++ in undefined behaviour, which means that anything can (and probably will, on some system) happen.

Depending on your compiler and its build configuration, you'll end up with a random value in x. In your case, it happens to be 0.0, but it can be any random value, depending on what data happened to occupy the piece of memory x happened to end up in.

In C++, it is generally considered very bad practise to not initialise member variables in the constructor, especially if you cannot guarantee that they will be initialised before they are being read.

What exactly do you expect "unknown" to mean? 0 is a perfectly reasonable value for an uninitialised variable with an unspecified value. It's just pure chance.

The important thing is that the float was not initialised, and in the passage you quote, BS doesn't talk about undefined behaviour because he's not referring to the syntax you're asking about, but instead about aggregate initialisation (and its variants).

It's worse than just arbitrary value. Even assuming that your compiler just uses the value left in memory and acts on the variable normally thereafter, the pre-existing bits could represent a floating-point trap value and end your program on first access.

But it goes even beyond that. Because the C++ Standard designates lvalue->rvalue conversion on uninitialized data as undefined behavior, the compiler is perfectly permitted to do anything it wants to your code, even the code that's unrelated to this variable, and even before the first access to this variable (as long as it can prove the undefined read of the variable is coming, which proof generally is easy only within the same basic block).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top