1

派生構造のすべてのメンバーをゼロに設定したいと考えています。

何百ものメンバーがあり、それ以上のメンバーが時々追加されるため、それらを明示的に初期化するとエラーが発生しやすいと感じます。

構造体には仮想関数がなく、すべてのメンバー フィールドが組み込みです。ただし、自明でないコンストラクターがあるため、それらは POD ではありません。

練習に対する標準的な眉をひそめることとは別に、次のことについて何か問題がありますか?

struct Base
{
    // Stuff
};

struct Derived : public Base
{
    // Hundreds of fields of different built-in types
    // including arrays

    Derived()
    {
        ::memset(reinterpret_cast<char*>this + sizeof (Base), 0, sizeof *this - sizeof (Base));
    }
};

ありがとう。

4

4 に答える 4

9

Baseこれは、基本クラスのサブオブジェクトがの先頭にあることを前提としていDerivedます。別の基本クラスを追加した場合、これは機能しません。

さらに、コードが間違っています。ポインタ演算は、バイトではなくオブジェクトの観点から実行されます。reinterpret_cast<char*>(this)バイト単位で算術演算を実行するには、を使用する必要があります。いずれにせよ、あなたはまだこれをするべきではありません。

値の初期化を利用した、次の、醜くない、標準に準拠したアプローチを検討してください。

struct Derived : public Base
{
    struct DerivedMembers { /* ... */ }

    DerivedMembers data;

    Derived() : data() { }
};

コンストラクターがない限りDerivedMembers、これはの各データメンバーの値を初期化します。これはdata、まさに希望する動作のように見えます。

dataまたは、 " "メンバー変数を使用せずにメンバーにアクセスできるようにする場合は、別の基本クラスの使用を検討してください。

struct DerivedMembers { /* ... */ }

struct Derived : Base, DerivedMembers
{
    Derived() : DerivedMembers() { }
};
于 2011-08-16T17:58:11.857 に答える
2

これを行うべきではありません。これを行う必要がないように、各クラスで初期化リストを使用する必要があります。最初のパスでそれを完了するのは非常に忙しい作業ですが、その後は練習に従えば簡単です。

この同様の質問を参照してください:

于 2011-08-16T18:00:43.270 に答える
2

すべての値を明示的にゼロに設定し、memset は移植できないため使用しないでください。コンパイラ/メモリの割り当てには、上書きする可能性のあるハウスキーピング データが格納されている場合があります。

于 2011-08-16T18:00:51.370 に答える
2

標準は「実践に眉をひそめる」ものではありません。未定義の動作になります。

例えば:

this + sizeof (Base)

C++ 標準には、この式が Derived へのポインターに解決されるという記述はありません。実際、 の型はthisisDerived * constであるため、実行したのはポインター演算です。C++ は、thisの配列へのポインターであるかのように、 に追加しようとします。これはおそらくあなたが望んでいたものではありません。Derivedthis[sizeof(Base)]

正しく行う方法がわからない場合は、未定義の動作の暗い廊下を歩かないでください。

最も重要なことは、体操を実際に機能させるように指示したとしても、コードは非常に壊れやすくなります。このバージョンのコンパイラでは動作するかもしれませんが、それ以降のバージョンでは失敗します。仮想関数を追加するような単純なことをすると、vtable ポインターが破棄されるため、コードに混乱Baseが生じます。

あなたにはいくつかの問題があるようです:

  1. 不要な派生。そのBase中に仮想的なものが何もないのなら、なぜあなたはそれから公に派生しているのですか?
  2. 太いインターフェース。クラスに数百のメンバーが含まれるようになった場合は、おそらくやりすぎです。
于 2011-08-16T18:08:28.087 に答える