10

C++ には、匿名のビットフィールド構造体を含むクラスがあります。すべてのフィールドを手動で書き出すことなく、ゼロに初期化したいと考えています。

初期化を 3 つの場所に配置することを想像できます。

  1. ビットフィールドにコンストラクターを作成する
  2. 含まれているクラスのコンストラクターの初期化子リストをゼロにします
  3. 含まれているクラスのコンストラクターの本体でゼロを設定します

このビットフィールドには多くのフィールドがありますが、すべてをリストするのは避けたいと思います。

たとえば、次のコードを参照してください。

class Big {
    public:
        Big();

        // Bitfield struct
        struct bflag_struct {
            unsigned int field1 : 1;
            unsigned int field2 : 2;
            unsigned int field3 : 1;
            // ...
            unsigned int field20 : 1;
            // bflag_struct(); <--- Here?
        } bflag;

        unsigned int integer_member;
        Big         *pointer_member;
}

Big::Big()
  : bflag(),             // <--- Can I zero bflag here?
    integer_member(0),
    pointer_member(NULL)
{
    // Or here?
}

これらのいずれかが望ましいですか?それとも、私が見逃しているものがありますか?

編集:以下の受け入れられた回答(Ferruccioによる)に基づいて、私はこの解決策に落ち着きました:

class Big {
    // ...

    struct bflag_struct {
        unsigned int field 1 : 1;
        // ...
        bflag_struct() { memset(this, 0, sizeof *this); };
    }

    // ...
}
4

7 に答える 7

13

コンストラクターでいつでもこれを行うことができます。

memset(&bflag, 0, sizeof bflag);
于 2009-03-04T20:54:45.713 に答える
9

ビットフィールド構造体を、0 に初期化しやすいものと結合します。

于 2009-03-04T20:56:33.663 に答える
6

ユニオンを使用することもできますが、フィールドにアクセスするときに間接的なレベルが追加されます。

class Big {
    union {
        struct {
            unsigned int field1 : 1;
            ...
        } fields;
        unsigned int all_fields;
    };
    ...
};

Big::Big()
  : all_fields(0),
    ...
{
    ...
}

MSVC では、union 内で無名構造体を使用できます (たとえば、 in の定義を参照D3DMATRIX) <d3d9.h>。ただし、これは非標準の C++ 拡張であるため、可能であれば使用を避ける必要があります。

于 2009-03-04T20:56:05.007 に答える
2

関数のような初期化子(「ここでbflagをゼロにできますか?」とマークされています)を使用すれば、POD構造体を0の値で初期化するのに100%十分です。

この点でコンパイラが壊れていることがわかっていない限り、これらのメンバーの追加の初期化を行うと、メリットがないために2回初期化されます。

編集:「楽しい」ために、VS2005、VS2008、GCC 3.4.4、GCC 4.2、およびBorland C++5.5.1でこれをチェックしました...BorlandC++5.5.1だけが間違っています。

そして、私は「間違っている」と言います。なぜなら、標準の8.5と8.5.1は、関数のような初期化子がPOD構造体をゼロ初期化する必要があることを意味しているように思われるからです。

于 2009-03-05T15:43:05.690 に答える
2

ところで C++20 は、クラス定義でのビットフィールドの初期化をサポートしています。

class ... {
   int foo : 1 {};
}

有効にする -std=c++2a を指定した gcc

于 2019-08-31T22:03:36.620 に答える
1

余談ですが、ビットフィールドがレガシー コードにインターフェイスする必要がない限り、使用しないでください。それらは本質的に移植性がなく、非効率的です。

于 2009-03-04T20:57:07.110 に答える
0

コンストラクターで ZeroMemory または memset を使用してメモリをゼロにすると、見た目がきれいになります。

于 2009-03-04T20:55:07.443 に答える