c++initializationundefined-behavior

Is use of uninitialized static object well-defined in C++?


In the following example,

#include <print>
struct C {
    int x;
};
int main() {
    static C obj = [] {
        obj.x = 3;
        return obj;
    }();
    std::print("{}", obj.x);
}

obj seems to be accessed before it finishes its initialization. Is it well-defined or not?


Solution

  • This code has undefined behavior.

    6.7.4/2 tells us:

    The lifetime of an object of type T begins when: [...] its initialization (if any) is complete

    8.9/3 says:

    Dynamic initialization of a block variable with static storage duration [...] is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization

    Since the lambda execution is before the completion of the initialization, the lifetime of obj has not yet begun. This leads us to the restrictions on use of such objects.

    See also footnote 21 on 6.7.4/7, which points out that before dynamic initialization of static storage duration objects is complete, lifetime has not begun, even though these objects are also zero-initialized before dynamic initialization happens.

    6.7.4/8:

    Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated [...] any glvalue that refers to the original object may be used but only in limited ways. [...] Otherwise, such a glvalue refers to allocated storage (6.7.6.5.2), and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if

    • the glvalue is used to access the object

    This line:

    obj.x = 3;
    

    is accessing the object through a glvalue before initialization has finished.

    Your program is undefined.