1

このように定義されたクラスであるクラスを見てきました..

class StringChild : public StringBase
    {
public:
    //some non-virtual functions
    static StringChild* CreateMe(int size);
private:
    unsigned char iBuf[1];
    };

静的ファクトリ関数には、次の実装があります。

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

私が理解している限り、この関数は新しい配置を使用してこのクラスを拡張しています。

メンバーが1つしかなく、ヒープに割り当てられているため、これは安全ですか?

4

3 に答える 3

6

これは、単純な C で可変長配列が利用できないことを回避するために使用された古い C のトリックです。次に、そこにオブジェクトを新しく配置します)。割り当てられたメモリの最後をさまよわない限り安全ですが、少なくとも一部のメモリ デバッガーを混乱させる傾向があります。

この手法を使用するときに絶対に確認しなければならないことの 1 つは、可変長配列がオブジェクト レイアウトの最後の要素であることです。そうしないと、他の内部変数をたどることになります。

ただし、ファクトリ関数の実装については少し疑わしいです-「サイズ」パラメーターが実際に目的の配列サイズであると思いますか? また、「delete」ではなく「free」を使用して上記のメモリを解放する必要があることを忘れないでください。後者はほとんどの場合に機能する可能性があります。

メモリをこのように管理しなければならない理由についてやむを得ない理由がない限り、配列を std::vector に置き換えるだけです。

于 2009-01-09T11:46:30.270 に答える
3

これは、iBuf が構造体の最後のメンバーである場合、POD では問題ありません。非 POD の問題は、たとえば、次のようなものである可能性があります。コンパイラは public/private/protected メンバーを自由に並べ替えることができ、仮想基本クラスは最も派生したオブジェクト IIUC の最後になります。

あなたの構造は非PODです(基本クラスがあります)ので、お勧めしません。

また、このようなインスタンスを作成すると

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

malloc によって取得されたメモリが free で解放されることを確認する必要があるため、次のようにインスタンスを削除します。

obj->~StringChild();
free(obj);

::operator new()割り当てに使用したいかもしれません

于 2009-01-09T12:01:06.700 に答える
0

厳密に言えば、安全ではないStringChildから派生したものです。StringBaseC++ 標準では、基本クラスのサブオブジェクトのレイアウトは指定されていません。第10条第3項:

最も派生したオブジェクト (1.8) で基本クラスのサブオブジェクトが割り当てられる順序は指定されていません。

POD 構造体である場合StringChild、そのような手法は安全です。

于 2009-01-09T12:04:55.193 に答える