0

私は複雑なクラスAを持っています:

class A{
...
};

クラスBはインクルードAのポインターであり、ポインターを返すメソッドがあります。

class B{
A* GetA(){return pA;}
A* pA;
};

次に、「GetA」を使用して A のポインターを取得する場合、次のように不正なポインターを使用する方が簡単です。

void func(A* p){
B b;
p = b.GetA();
}

「func」を使用すると、不正なポインターが取得されます。上記のコードは単なるサンプルです。マルチスレッド環境では、この間違いを犯しやすいことがわかりました。

これらの間違いを確実に回避する方法はありますか?

どうもありがとう

4

2 に答える 2

2

C++ には、不正なポインター アクセスから身を守るための一般的な方法はありませんが、身を守るために使用できるイディオムがあります。

クラスを概念/オブジェクトを表すものとして保持し、それらに含まれる可能性のあるポインターへの直接アクセスを公開しないでください。たとえば、記述的なメソッド、またはコンテナのようなクラスbegin/endスタイル メソッドを優先します。

ポインターを管理するときは、最初に などの標準コンテナーを使用することをお勧めしますvector。それらは高度に調整およびデバッグされており、適切なコンストラクター、代入、デストラクタなどをすべて備えているため、多くの問題を防ぐことができます。

標準のコンテナーが使用できない場合は、ポインターのニーズに応じて、、、またはなどのスマート ポインターを使用してunique_ptrください。適切なスマート ポインターを使用することで、意図せずにコーディングの間違いを犯すことはほとんどなくなります。scoped_ptrshared_ptrweak_ptr

これらすべてのガイドラインを使用しても、実装しようとした保護をいつでも回避できます。多くのキャストを使用していることに気付いた場合は、一歩下がって設計を再検討する必要があります。

あなたの場合pA、アクセサーを介してアクセスできないようにするだけでなく、生のポインターにもしません。

于 2012-08-02T16:55:09.560 に答える
0

コンストラクターのポインターをNULLに初期化する場合:

class B {
    B() {
        pA = NULL;
    }
    A* GetA(){return pA;}
    A* pA;
}

次に、ポインタを使用する前に、ポインタがNULLでないかどうかを確認できます。

void func(A* p){
    B b;
    p = b.GetA();
    if(p != NULL) {
        //use p
    }
}

また、関数へのポインタを渡してから、最初に関数を使用せずに関数に割り当てるのは奇妙に思えます。p = b.GetA();以外は変更されませんfunc。おそらくあなたはこれらのようなことをするつもりですか?

//Caller passes reference to their pointer, caller's pointer gets set.
void func(A *&p) {
    B b;
    p = b.GetA();
}
//Caller passes pointer to their pointer, caller's pointer gets set.
void func(A **p){
    B b;
    if(p != NULL) {
        *p = b.GetA();
    }
}
于 2012-08-02T17:00:48.163 に答える