考虑以下课程:
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()。 / p>
话虽如此,这样做总是安全的吗?或者可以在一些奇怪的角落中多个虚拟继承与其他疯狂的情况下std :: uint8_t [sizeof(T)]没有分配足够的空间?
答案 0 :(得分:12)
R上。 Martinho Fernandes打败了我!使用
typename std::aligned_storage<sizeof(T)>::type memory;
你很高兴。有关详细信息,请参阅here。
正如我们的评论员小组指出的那样,默认对齐方式总是足够的,但可能更多严格要求类型(因此您需要额外填充空间)。您可以通过明确指定它来避免这种情况:
typename std::aligned_storage<sizeof(T), alignof(T)>::type memory;