Search code examples
c++c++17mallocplacement-new

Explicit creation of objects with a trivial default constructor using placement-new in C++17


My understanding is that the rules about implicit creation of implicit-lifetime objects applies only to C++20 and newer. I'm stuck with C++17, so I wondered if I could fix this example code (so that it is not UB in C++17) by adding a placement-new expression that doesn't initialize the object, like this:

#include <cstdlib>
#include <new>

struct X { int a, b; };

// I believe writing to the fields of the returned object is UB in C++17, OK in C++20 and later.
X* make_uninitialized_x() {
    auto p = (X*)std::malloc(sizeof(X));
    return p;
}

// Is writing to the fields of the returned object OK in C++17 and earlier?
X* make_uninitialized_x_fixed_for_cpp17() {
    auto p = (X*)std::malloc(sizeof(X));
    new (p) X;  // This gets optimized away with -O1 flag
    return p;
}

Solution

  • Answering my own question: According to the comments, either one of the fixed functions below would be OK in C++17 and earlier.

    #include <cstdlib>
    #include <new>
    
    struct X { int a, b; };
    
    X* make_uninitialized_x_fixed_v1() {
        auto p = (X*)std::malloc(sizeof(X));
        new (p) X;
        return std::launder(p);
    }
    
    X* make_uninitialized_x_fixed_v2() {
        auto p = (X*)std::malloc(sizeof(X));
        return new (p) X;
    }