4

変数、特にポインターが C++ で定義されているかどうかを確認するにはどうすればよいですか? クラスがあるとします:

class MyClass {  
public:

    MyClass();

    ~MyClass() {
        delete pointer; // if defined!
    }

    initializePointer() {
        pointer = new OtherClass();
    }

private:

    OtherClass* pointer;

};
4

8 に答える 8

22

ポインター値のチェックについて心配する必要はありません。null ポインター値に初期化してから、delete を呼び出すだけです。null ポインターの削除は何もしません (標準で保証されています)。

class MyClass {  
public:

    MyClass():pointer(0) { }

    ~MyClass() {
        delete pointer;
        pointer = 0;
    }

    initializePointer() {
        pointer = new OtherClass();
    }

private:

    OtherClass* pointer;

};

また、delete を呼び出すたびに、ポインタを null ポインタ値に設定する必要があります。それでは皆さん元気です。

于 2008-12-19T18:14:56.540 に答える
8

オブジェクトの構築時にポインタ値を NULL に初期化する傾向があります。これにより、ポインタ変数が定義されているかどうかを確認するために NULL に対するチェックが可能になります。

于 2008-12-19T18:06:31.517 に答える
6

0( ) のチェックに加えてNULL、コードをリファクタリングして、ポインタが常に有効になるようにすることも 1 つの解決策です。これは常に可能というわけではありませんが、ほとんどの場合、これが最善の解決策です。

あなたの場合(他のほとんどの場合と同様)、これはコンストラクターでポインターを初期化し(つまり、ライフタイムが開始するとすぐに)、ライフタイムの終わりに破棄することを意味します。変数を作成し、変数へのprivate直接書き込みアクセスを許可しないで、変数が常に有効になるようにします。

これは C++ でよく使用されるパターンであり、ポイント対象のオブジェクトの有効期間をクラスの有効期間に効果的に制限します。reset場合によっては、ポインターを削除してすぐに再初期化するようなものを提供することが実行可能な解決策になることもあります。これが例外セーフな方法で記述されている場合は、ポインタが決して無効にならないことも保証されています。

ポインタの有効性を追跡するために ean フラグを作成しないでください。boolこのソリューションには、ポインタを に設定する利点はなく、多くの欠点があります0

于 2008-12-19T18:12:21.693 に答える
4

コンストラクターの要点は、完了後にすべてのメンバー変数が正しく定義されることです。この場合、NULL が有効な初期値です。

NULL での削除の呼び出しは明確に定義されています。

通常は、コンストラクターが RAW ポインターの値を定義することを期待します。また、オブジェクトには RAW ポインターが含まれており、明らかにそれを所有しているため (それを削除しているため、これは所有権を意味します)、コピー コンストラクターと代入演算子のコンパイラ生成バージョンをオーバーライドすることも確認する必要があります。

class MyClass
{  
    public:
        MyClass()
            :pointer(NULL)  // valid value.
        {}
        ~MyClass()
        {
            delete pointer; // This is fine.
        }

        void initializePointer() // Missing return type
        {
            pointer = new OtherClass();
        }

    private:
        MyClass(MyClass const& copy);           // If you don't define these 
        MyClass& operator=(MyClass const& copy);// two the compiler generated ones
                                                // will do nasty things with owned
                                                // RAW pointers.

        OtherClass* pointer;
};

または、標準のスマート ポインターのいずれかを使用できます。オブジェクトを本当にコピー可能にしたい場合を除き、おそらく std::auto_ptr<> です。

于 2008-12-19T18:49:57.653 に答える
2

コンストラクターでは常にポインターを NULL に初期化する必要があります。そうすれば、デストラクタが初期化されているかどうかを確認できます。また、次のようにコンストラクターの引数リストで行う方が効率的です。

MyClass::MyClass() : pointer(NULL)
{
}

MyClass::~MyClass()
{
    if(pointer != NULL) { delete pointer; }
}

同様に、プログラムの存続期間中にオブジェクトが何度も再初期化される場合は、値を削除するときに値を NULL に設定し、割り当てるときに値を null に対してチェックする必要があります。ただし、デストラクタで値を NULL に設定しても、オブジェクトは明らかに破棄されるため、違いはありません。

(コンストラクターで明示的に "pointer = NULL;" と言う代わりに) この方法で行う利点は、コンパイラーが既にこのような代入を暗黙的に行っていることです。手動で割り当てを行うと、それが 2 回行われますが、大きなループなどでクラスの多くのインスタンスを作成している場合を除いて、通常は大したことではありません。

于 2008-12-19T18:07:26.727 に答える
1

あなたはできません、私の知る限り。標準的な方法は、有効な値が含まれていない場合に NULL に設定することです。そのポイントの周りに無効なメモリへのポインターを残すことは、どのような状況でも悪い習慣です。これに固執する場合は、常に NULL をチェックして、「定義済み」かどうかを確認できます。

于 2008-12-19T18:08:07.833 に答える
1

本当の答えは litb の答えですが、私はサイドコメントをしたかっただけです。スマート ポインター (この場合は std::auto_ptr で十分) を使用すると問題が解決され、デストラクタでポインターを削除することを覚えておく必要がないという利点があります。実際、デフォルトのデストラクタ (コンパイラによって生成される) がメモリ リソースを処理します。

コメントをさらに一般的にすると、ポインタの二重削除を避けるために、クラスで代入演算子とコピー コンストラクタをプライベートとしてマークする (定義されていない) か、手動で定義する必要があります。コンパイラーが提供する operator== とコピー コンストラクターはポインターをコピーするだけで、最終的には二重削除になります。これは、std::auto_ptr を auto_ptr のコピー セマンティクスの奇妙さを加えて使用する場合にも考慮する必要があるため、ここに記述します。

于 2008-12-19T18:47:36.787 に答える
1

まだ言及されていない追加の答えは、生のポインターの代わりにスマートポインターオブジェクトを使用することです。その後のポインターの使用方法に応じて、std::auto_ptrboost::shared_ptr、または他の多くのスマート ポインター クラスがここで適切な場合があります。 仕組みを少しboost::scoped_ptr変えればうまくいくかもしれません。initializePointer()

こうすることで、スマート ポインターはそれが有効かどうかを記憶し、それを含むオブジェクトが破棄されたときにそれ自体を削除します。

class MyClass {  
public:

    MyClass();

    ~MyClass() {
    }

    initializePointer() {
        pointer.reset( new OtherClass());
    }

private:

    std::auto_ptr<OtherClass> pointer;

};
于 2008-12-19T18:49:17.513 に答える