Безопасно ли сочетать sizeof и размещение новых?

Рассмотрим следующий класс:

template <class T>
class defer {
public:
template <class ...Args>
void construct(Args&&...);
T& obj();
~defer();
private:
std::uint8_t memory[sizeof(T)];
T * ptr();
};

template <class T>
template <class ...Args>
void defer<T>::construct(Args&& ...args) {
new(static_cast<void*>(&memory[0])) T(std::forward<Args>(args)...);
}

template <class T>
T& defer<T>::obj() {
return *(ptr());
}

template <class T>
defer<T>::~defer() {
ptr()->~T();
}

template <class T>
T * defer<T>::ptr() {
return static_cast<T*>(&memory[0]);
}

СЕЙЧАС Я ЗНАЮ, что есть проблемы с этим, но для того, чтобы сделать код коротким для целей обсуждения, мы будем предполагать, что defer :: construct () всегда вызывается до того, как объект выходит из области видимости.

При этом всегда ли это безопасно делать? Или может в каком-то странном угловом случае множественного виртуального наследования с другим сумасшествием std :: uint8_t [sizeof (T)] не выделить достаточно места?

2

Решение

Р. Мартиньо Фернандес опередил меня! использование

typename std::aligned_storage<sizeof(T)>::type  memory;

и ты в порядке. Увидеть Вот для деталей.


Как указала наша группа комментаторов, выравнивания по умолчанию всегда достаточно, но может быть Больше строгий, чем требуется для вашего типа (так что вы тратите пространство с дополнительными дополнениями). Вы можете избежать этого, просто указав это явно:

typename std::aligned_storage<sizeof(T), alignof(T)>::type memory;
12

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]