2

簡単な質問:

単純なベクトル クラスがある場合:

class Vector
{
public:
  float x;
  float y;
  float z;
};

RAII の概念はここにも当てはまりますか? つまり、すべての値をいくつかの値に初期化するコンストラクターを提供します (初期化されていない値が使用されるのを防ぐため)。

EDITまたは、オブジェクトを難読化する前にメンバー変数を初期化するようユーザーに明示的に要求するコンストラクターを提供します。

すなわち

class Vector
{
public:
  float x;
  float y;
  float z;
public:
  Vector( float x_, float y_, float z_ )
    : x( x_ ), y( y_ ), z( z_ )
  { // Code to check pre-condition; }
};

プログラマーが値を使用する前に値を初期化するのを忘れるのを助けるために RAII を使用すべきですか、それとも開発者の責任ですか?

それとも、RAII の見方が間違っているのでしょうか。

私は意図的にこの例を途方もなく単純にしました。私の本当の質問は、たとえば次のような複合クラスに答えることでした。

class VectorField
{
public:
  Vector top;
  Vector bottom;
  Vector back;

  // a lot more!
};

ご覧のとおり...すべてのメンバーを初期化するためにコンストラクターを作成する必要がある場合、それは非常に面倒です。

考え?

4

5 に答える 5

3

明示的なクリーンアップを行う必要があり、別のオブジェクトが暗黙的にクリーンアップされるのと同時にそのクリーンアップを実行したい場合は、RAII パターンを使用します。これは、メモリの割り当て/割り当て解除、クリティカル セクションのエントリ/終了、データベース接続などで発生する可能性があります。例では、「フロート」は自動的にクリーンアップされるため、心配する必要はありません。ただし、ベクトルを取得するために呼び出した次の関数があるとします。

Vector* getMeAVector() {
    Vector *v = new Vector();
    // do something
    return v;
}

そして、返されたベクトルを削除するのは呼び出し元の責任であるとします。このコードを次の方法で呼び出した場合:

Vector *v = getMeAVector();
// do some stuff with v
delete v;

ベクトルを解放することを忘れないでください。「もの」が例外をスローする可能性のある長いコードである場合、またはそこに多数の return ステートメントがある場合は、すべての出口ポイントでベクトルを解放する必要があります。あなたがそうしても、別の「return」ステートメントを追加したり、例外をスローするライブラリを呼び出したりしてコードを維持する人はそうしないかもしれません。代わりに、次のようなクラスを作成できます。

class AutoVector
{
        Vector *v_;
    public:
        AutoVector(Vector *v) : v_(v) {}
        ~AutoVector() { delete v_; }
};

次に、次のようにベクトルを取得できます。

Vector *v = getMeAVector();
AutoVector av(v);
// do lots of complicated stuff including throwing exceptions, multiple returns, etc.

av が範囲外になると自動的に削除されるため、ベクトルの削除について心配する必要はもうありません。必要に応じて、"AutoVector av(v)" 構文をもう少し良くするための小さなマクロを作成することもできます。

これは少しわざとらしい例ですが、周りのコードが複雑だったり、例外をスローする可能性がある場合や、誰かがやってきて途中で「return」ステートメントを追加する場合は、「AutoVector」がメモリを解放してくれるといいですね。自動的。

ctor でクリティカル セクションに入り、dtor で終了する「auto」クラスでも同じことができます。

于 2009-04-24T03:02:00.297 に答える