3
template<typename T>
someclass<T>& operator=(const someclass<T>& other)
{
    typename std::vector<T *>::const_iterator rhs;
    typename std::vector<T *>::iterator lhs;

    //identity test
    //this->data is std::vector<T *>

    for(lhs = this->data.begin(); lhs != this->data.end(); lhs++)
    {
        delete *lhs;
    }

    this->data.clear(); // this is what I forgot

    this->data.reserve(other.data.size());
    for (rhs = other.data.begin(); rhs != other.data.end(); rhs++)
    {
        if (NULL == *rhs)
        {
            this->data.push_back(NULL);
        }
        else
        {
            this->data.push_back(new T(**rhs));
        }
    }
}

コメントでわかるように、配列内の古いポインターを消去するのを忘れていました。代入演算子を 2 回目に呼び出したとき、ダブル フリーについて不平を言う glibc エラーが発生しました。提供された唯一の情報は、削除された住所でした。

これは、そのような削除されたポインターのクラスをどうするかについて考えさせます-それらを再度削除したくない場合、および削除した場合、それは確かにエラーです。別の削除が正しいため、それらを NULL に設定することはできません。新しく作成されたオブジェクトにメモリの場所を割り当てることができるため、値を保持したくありません。

デバッグに適しているのは、INVALID などの値です。これらのポインターに割り当てる値は、「このポインターで delete を呼び出しても何も起こらない」という NULL の代わりに、「このポインターで delete を呼び出すとエラーです」と表示されます。このようなものはありますか?

4

2 に答える 2

6

いいえ。所有権のセマンティクスが必要な場合は、生のポインターを使用しないことをお勧めします。タイプを「dataまたはboost::ptr_vector<T>std::vector<std::unique_ptr<T>>にすると、ポインタの存続期間を手動で管理する必要がなくなり、問題は解決します。

提示した代入演算子は、別のコンテナに割り当てられたときにコンテナ内のオブジェクトをスライスするため、コンテナはポリモーフィックオブジェクトを適切にサポートしていません。さらに良い解決策は、を持っていることかもしれませんstd::vector<T>。これは、ポインターのコンテナーの他のプロパティ(要素へのポインターの非無効化、または潜在的に高速なソート操作など)を期待していない場合にのみ適切です。

于 2011-10-11T08:07:21.723 に答える
2

この問題の解決策は、削除を含まないコードを作成することです。可能な場合は使用してくださいshared_ptr。ポリモーフィックオブジェクトを所有するコンテナがある場合は、ポインタコンテナを使用することもできます。

于 2011-10-11T08:07:49.803 に答える