6

無制限の労働組合とその実際の適用についていくつか質問があります。次のコードがあるとします。

struct MyStruct
{
    MyStruct(const std::vector<int>& a) : array(a), type(ARRAY)
    {}
    MyStruct(bool b) : boolean(b), type(BOOL)
    {}
    MyStruct(const MyStruct& ms) : type(ms.type)
    {
        if (type == ARRAY)
            new (&array) std::vector<int>(ms.array);
        else
            boolean = ms.boolean;
    }
    MyStruct& operator=(const MyStruct& ms)
    {
        if (&ms != this) {
            if (type == ARRAY)
                array.~vector<int>(); // EDIT(2) 
            if (ms.type == ARRAY)
                new (&array) std::vector<int>(ms.array);
            else
                boolean = ms.boolean;
            type = ms.type;
        }
        return *this;
    }
    ~MyStruct()
    {
        if (type == ARRAY)
            array.~vector<int>();
    }

    union {
        std::vector<int> array;
        bool             boolean;
    };
    enum {ARRAY, BOOL} type;
};
  1. このコードは有効ですか :) ?
  2. ブール値を使用するたびにベクトル デストラクタを明示的に呼び出す必要がありますか (ここで説明されているようにhttp://cpp11standard.blogspot.com/2012/11/c11-standard-explained-1-unrestricted.html )
  3. 'array = ms.array' のようなことをするだけでなく、配置 new が必要なのはなぜですか?

編集:

  • はい、コンパイルされます
  • 「匿名共用体内で宣言されたメンバーは、実際には包含クラスのメンバーであり、包含クラスのコンストラクターで初期化できます。」(非自明なメンバーを持つ C++11 の無名共用体)
  • 提案されているように明示的なデストラクタを追加すると、g++ 4.8 / clang 4.2 で SIGSEV が発生します
4

2 に答える 2

2

共用体は、既定のコンストラクター、コピー コンストラクター、コピー代入演算子、またはデストラクターを宣言しません。

std::stringが特別なメンバー関数の重要なバージョンを少なくとも 1 つ宣言する場合 (これは事実です)、前述のものはすべて暗黙的に削除され、それらを宣言 (および定義) する必要があります (... それらが使用されている場合、これはケース)。

その限りでは、そのコードは正しくなく、正常にコンパイルされるべきではありません (これは、標準の 9.5 par 3 の例とほぼ同じですが、std::stringではなくstd::vectorです)。
(正しく指摘されているように、匿名組合には適用されません)

質問 (2) について: ユニオンを安全に切り替えるには、これが必要です。標準では、9.5 par 4 [注] で明示的に述べています。
考えてみればそれも一理あります。いつでも最大 1 つのデータ メンバーをアクティブにすることができunion、それらは魔法のようにデフォルトで構築/破棄されるわけではありません。つまり、適切に構築/破棄する必要があります。unionそれ以外の場合は、 を別のものとして使用することは意味がありません (または定義されていません) (とにかくそれができないわけではありませんが、未定義です)。
オブジェクトはポインターではなく、ヒープに割り当てられているかどうかもわかりません (ヒープに割り当てられていても、別のオブジェクトにあるため、削除することはできません)。delete? オブジェクトを削除できなくても、リークせずに (場合によっては数回) オブジェクトを割り当てるにはどうすればよいでしょうか? これは多くの選択肢を残しません。その限りでは、[注] は完全に理にかなっています。

于 2013-05-21T06:28:31.027 に答える