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.マルティーニョ・フェルナンデスが私を打ち負かしました!使用する

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

そして、あなたは行ってもいいです。詳しくはこちらをご覧ください。


コメンテーターのパネルが指摘したように、デフォルトの配置は常に十分ですが、タイプに必要なよりも厳しい場合があります (余分なパディングでスペースを無駄にします)。明示的に指定するだけでこれを回避できます。

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