2

考虑以下类:

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)] 可以不分配足够的空间吗?

4

1 回答 1

12

R. Martinho Fernandes 打败了我!采用

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

你可以走了。有关详细信息,请参见此处


正如我们的评论员小组所指出的那样,默认对齐总是足够的,但可能比您的类型要求的严格(因此您会浪费额外的填充空间)。您可以通过明确指定它来避免这种情况:

typename std::aligned_storage<sizeof(T), alignof(T)>::type memory;
于 2012-10-25T15:52:24.707 回答