1

私の目標は、いくつかの共通データを共有するクラス階層のクラスのインスタンスを作成することです。割り当てられたメモリで最大のインスタンスを作成できるように、( union を使用して) 十分なメモリを作成します。ここで、クラスのインスタンスを作成/交換し、そこのメモリで「古い」データを使用したいと考えています。これは有効な/合法的な操作ですか?

元のコードでは、いくつかの MTP を使用して共用体を作成しています。ターゲットは、このクラス階層をステート マシン実装のコアとして使用することです。ここでは、問題を含む基本的なコードのみを示します。

基本クラスに仮想メソッドが含まれていなくても、派生クラスには含まれていると問題になることがわかりました。これは、vtable-pointer がメモリの前に移動するためです (x86/linux の gcc を使用)。

簡単な質問: 基本クラスのインスタンスが以前に作成されていて、その派生クラスのインスタンスでメモリが再利用されている場合、派生クラスのインスタンスは基本クラスのデータにアクセスできますか?

class Base
{
    public:
        int a;
        Base()=default;
        Base( int _a):a(_a){}

        void Print() { cout << "Value: " << a << endl; }
};

class Derived1: public Base
{
    public:
        int d;

        Derived1(): d( 0x11223344){}
};

union  U
{   
    U(){}
    Base base;
    Derived1 derived1;
} u;

int main()
{
    memset( &u, 0, sizeof(u));

    new (&u) Base(12345678);
    u.base.Print();

    new (&u) Derived1;
    u.base.Print();
 }
4

2 に答える 2

1

いいえ、サンダードが言うので、これはうまくいきません:

9.5/1 :ユニオンでは、非静的データ メンバーの最大 1 つをいつでもアクティブにできます。つまり、非静的データ メンバーの最大 1 つの値をいつでもユニオンに格納できます。

あなたがやろうとしているのは、未定義の動作です:

new (&u) Derived1;  // RISKY !!!

配置 new を使用すると、以前に u にあったオブジェクトを正しく破棄せずに上書きします。次に、の作成Derived1はとにかく独自のベースを作成します。何らかの方法で古い値をメモリに保持することができたとしても、それはまだ未定義の動作です。オブジェクトのレイアウトとコンパイラの実装に応じて、動作するかどうかが決まります。

于 2015-04-25T12:40:43.090 に答える
0

これは未定義の動作です。動作しているように見えるかもしれませんが、移植性がなく、依存するべきではありません。

ユニオンはアクティブなメンバーを 1 つだけ持つことができます。を構築するDerived1と、以前のものは無効になります。

于 2015-04-25T12:40:51.713 に答える