Search code examples
c++arraysinitializationc++14default-constructor

Creating an uninitialized array of items which have default constructors?


Given a class Foo which has some value-initializing default constructor:

class Foo {
private:
    uint32_t x;

public:
    constexpr Foo()
        : x { 3 }
    {}
    // ... and some other constructors
};

I need to allocate an array of these Foo's. I don't want the array's elements' default constructors to run, because later I'm going to initialize each element explicitly anyway. Something like this:

Foo foos[20000];

for (int i = 0; i < 20000; ++i) {
    foos[i] = init(i);
}

Is there a way to obtain such an uninitialized array of Foo's given that we're not allowed to change the default constructor of Foo into a non-initializing one?

By the way, this is how you'd create an uninitialized array in D:

Foo[20000] foos = void;

...and here's the same in Rust:

let mut foos: [Foo; 20000] = unsafe { std::mem::uninitialized() };

Solution

  • Perhaps this answers the question at hand more accurately?

    #include <type_traits>
    
    class Foo {
    private:
        uint32_t x;
    
    public:
        constexpr Foo()
            : x { 3 }
        {}
    
        constexpr Foo(uint32_t n)
            : x { n * n }
        {}
    };
    
        // ...and then in some function:
    
        typename std::aligned_storage<sizeof(Foo), alignof(Foo)>::type foos[20000];
    
        for (int i = 0; i < 20000; ++i) {
            new (foos + i) Foo(i);
        }
    

    The drawback seems to be that you can use only a constructor to initialize those elements, and not a free function or anything else.

    Question: Can I then access those Foo's like this:

        Foo* ptr = reinterpret_cast<Foo*>(foos);
        ptr[50] = Foo();