0

さて、あなたたちは私の最後の質問で非常に役に立ちました、それで私は別の質問を試みます。これも宿題で、最後のものはかなり古いものでしたが、提出されており、マークが付けられるのを待っています。ですから、私を噛むものがあれば、おそらくこの問題でしょう。(他の学生のために)課題を提出することはまだ可能であるため、私はクラス名などを難読化しました。

オブジェクトへのポインタのみをメンバーとするクラスがあります。このクラスは、現在保持しているポインター(Object *o_基本クラス)からの特定の操作を公開するように構築されていますObject{1, 2, 3, ...}。これで、メモリリークやクラッシュなしに、次のことができるようになりました。

std::vector<ObjectPtr> v;
v.push_back(ObjectPtr(new Object1(..., ..., ...)));
v.push_back(ObjectPtr(new Object2(..., ...)));
v.push_back(ObjectPtr(new Object1(.., .., ..)));

// Copy Constructor Ptr
std::vector<ObjectPtr> v2(v);
// Assignment Operator Ptr
std::vector<ObjectPtr> v3;
v3 = v2;

これはすべて機能し、メモリリークはありません。しかし、ファイルから内容を読み込もうとすると、istream_iterator<ObjectPtr>リークが発生し始めます。ObjectPtrは、動的メモリを処理する唯一のクラスであり、Object *o_NULLに設定されるか、によって割り当てられObject{1, 2, 3, ...}ます。

読み取るファイルは次のようになります

Object1
..。
..。
Object2
..。
..。
Object1
..
std::ifstream is("file.txt");
std::istream_iterator<ObjectPtr> in(is), end;
for (; in != end; ++in)
    cout << *in << "\n";

ObjectPtrこれらの値を読み取るために使用されるフレンド関数は、次のようになります。

friend istream &operator>>(istream &is, ObjectPtr &op) {
    std::string tmp;
    while (std::getline(is, tmp)) {
        if (tmp == "Object1") {
            op.o_ = new Object1;
            return is >> (Object1 &)*(op.o_); // Send it to operator>> for Object1
        }
        if (tmp == "Object2") {
            op.o_ = new Object2;
            return is >> (Object2 &)*(op.o_);
        }
        ...
    }
    return is;
}

ここのどこかでそれは私にユニコーンを始めます、そして私は本当に理由を知りたいです。

一言で言えば、istream_iteratorは、代入およびコピーコンストラクターが適切に機能しているときにメモリをリークします。これにより、クラスが正しく構築されていると信じられObject{1, 2, 3, 4, ..}、問題は内にありますoperator>>

4

1 に答える 1

2

これが私に最初に起こることです。それがあなたが探している問題であるかどうかはわかりません:

friend istream &operator>>(istream &is, ObjectPtr &op) {
    std::string tmp;
    while (std::getline(is, tmp)) {
        if (tmp == "Object1") {
            op.o_ = new Object1;

その最後の行で、?の古い値はどうなりop.oますか?
オブジェクトへのストリーミングとは、完全に構築されたオブジェクトへのストリーミングを意味し、オブジェクトの古いデータに注意する必要があることを忘れないでください。(そのため、コンストラクターが使用することを好むことがよくstd::istreamあります。次の瞬間に変更されるオブジェクトの初期化を安全にする複雑なオブジェクトの場合。)

ObjectPtr代入演算子やswap()メンバー関数はありますか?その場合、新しいオブジェクトを作成し、それをに割り当てたり、と交換したりすることで、入力演算子を実装する方が簡単な場合がありますop

于 2010-07-18T19:41:32.890 に答える