Are std::optional members stored contiguously?
Asked Answered
C

2

5

I suppose I'm a bit confused as to how exactly optional values are stored. When constructing a class or struct that contains std::optional<T> members, will these members be stored contiguously in memory or does optional allocate dynamically? For example, would the below struct be one contiguous block of memory?

struct Material
    {
        std::string name;
        std::optional<size_t> albedo;
        std::optional<size_t> normal;
        std::optional<size_t> metalness;
        std::optional<size_t> roughness;
        std::optional<size_t> ao; // ambient occlusion
        bool hasAlphaChannel = false;
    };
Clintclintock answered 10/6, 2021 at 14:18 Comment(1)
Aside from std::optional internal storage you still have the concern of padding that may result in your members being non-contiguous.Pliocene
S
14

optional is required to not use dynamic allocation.

If an optional contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place. Thus, an optional object models an object, not a pointer, even though operator*() and operator->() are defined.

https://en.cppreference.com/w/cpp/utility/optional

There is also the member variables of optional and also padding that can occur. so no, they are not necessarily contigous, but they are within the object you declare them in.

Sabadilla answered 10/6, 2021 at 14:23 Comment(0)
P
3

According to the standard std::optional is prohibited to use dynamic memory for their direct members.

One possible layout could for example be:

template<class T>
class optional
{
    bool engaged;
    union {
        T value;
        unsigned char reserved;
    };
};
Paff answered 10/6, 2021 at 14:22 Comment(5)
reserved is unnecessaryWagtail
The name is not optional in this context.Paff
The entire member named reserved is unnecessary. union { T value; } is valid.Wagtail
@yurikilochek Why use a union in the first place?Casey
@Casey Because the T might not have a default constructor. When placed inside a union, the value is not initialized unless explicitly initialized with placement new (or some other initialization procedure).Paff

© 2022 - 2024 — McMap. All rights reserved.