Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually constructing a trivial base class via placement-new

Beware, we're skirting the dragon's lair.

Consider the following two classes:

struct Base {
    std::string const *str;
};

struct Foo : Base {
    Foo() { std::cout << *str << "\n"; }
};

As you can see, I'm accessing an uninitialized pointer. Or am I?

Let's assume I'm only working with Base classes that are trivial, nothing more than (potentially nested) bags of pointers.

static_assert(std::is_trivial<Base>{}, "!");

I would like to construct Foo in three steps:

  1. Allocate raw storage for a Foo

  2. Initialize a suitably-placed Base subobject via placement-new

  3. Construct Foo via placement-new.

My implementation is as follows:

std::unique_ptr<Foo> makeFooWithBase(std::string const &str) {

    static_assert(std::is_trivial<Base>{}, "!");

    // (1)
    auto storage = std::make_unique<
        std::aligned_storage_t<sizeof(Foo), alignof(Foo)>
    >();

    Foo * const object = reinterpret_cast<Foo *>(storage.get());
    Base * const base = object;

    // (2)
    new (base) Base{&str};

    // (3)
    new (object) Foo(); 

    storage.release();
    return std::unique_ptr<Foo>{object};
}

Since Base is trivial, my understanding is that:

  • Skipping the trivial destructor of the Base constructed at (2) is fine;

  • The trivial default constructor of the Base subobject constructed as part of the Foo at (3) does nothing;

And so Foo receives an initialized pointer, and all is well.

Of course, this is what happens in practice, even at -O3 (see for yourself!).
But is it safe, or will the dragon snatch and eat me one day?

like image 257
Quentin Avatar asked Mar 22 '17 09:03

Quentin


People also ask

Which class is used to design the base classes?

Explanation: Abstract class is used to design base class because functions of abstract class can be overridden in derived class hence derived class from same base class can have common method with different implementation, hence forcing encapsulation.

What is base class example?

Techopedia Explains Base Class A class derived from a base class inherits both data and behavior. For example, "vehicle" can be a base class from which "car" and "bus" are derived. Cars and buses are both vehicles, but each represents its own specialization of the vehicle base class.

What is base class method?

A base class access is permitted only in a constructor, an instance method, or an instance property accessor. It is an error to use the base keyword from within a static method. The base class that is accessed is the base class specified in the class declaration.

Can we create instance of base class?

Answer: No. In general, When we create object of a class, its reference is stored in stack memory and object is stored in heap and address of object is assigned to class reference. Child objch is child class reference created on stack memory.


1 Answers

This seems to be explicitly disallowed by the standard. Ending an objects lifetime, and starting a new objects lifetime in the same location is explicitly allowed, unless it's a base class:

§3.8 Object Lifetime

§3.8.7 - If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:

  • the storage for the new object exactly overlays the storage location which the original object occupied, and

  • the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and

  • [snip] and

  • the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).

like image 59
sp2danny Avatar answered Nov 03 '22 19:11

sp2danny