4

重複の可能性:
3 つのルールとは?

次のプログラムでメモリが二重に解放されるという問題があります。

デバッガーは、問題がpush_back()関数にあることを示しています。

クラスA:

class A {
    public:
        A(int x);
        int x;
};

A::A(int x) {
    this->x = x;
}

クラス B:

class B {
    public:
        B(int x);
        ~B();
        A* a;
};

B::B(int x) {
    this->a = new A(x);
}

B::~B() {
    delete a;
}

主な機能:

int main() {
    vector<B> vec;

    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i)); <------------ Issue is here
    }

    cout << "adding complete" << endl;

    for(int i = 0; i < 10; i++) {
        cout << "x = " << (vec[i].a)->x << endl;
    }

    return 0;
}

このコードのどこが間違っていますか?

編集:エラーdouble free or memory corruption

4

3 に答える 3

6

コピー コンストラクターとコピー代入演算子を定義するのを忘れたので、ラップされたオブジェクトがdeleteいくつかによって d されていBますB

この場合、それB(i)は特定した行の一時的なものであり、ベクター内の実装定義のコピー数です。

3 のルールを遵守します。

于 2012-11-12T16:12:45.217 に答える
4

コードの問題は、「プレーンな」C/C++ ポインターには所有権の概念がないという事実によるものです。ポインタがコピーされると、両方のコピーが*データを所有していると「考え」、二重削除につながります。

この事実を認識して、C++ 標準ライブラリの設計者は、このunique_ptr<T>ような問題に対処するのに役立つクラスを導入しました。


*ポインタの 1 つのコピーは、B渡された のインスタンスにありますpush_back。ポインタのもう一方のコピーは、 に入力されたインスタンスにありますvector

于 2012-11-12T16:12:54.200 に答える
2

3 のルールに留意する

他の誰もがすでにこれについて口論しているので、私はこれ以上飛び込みません.

達成しようとしているように見える使用法に対処する (そして消去の過程で 3 つのルールに準拠する) には、次のことを試してください。動的メンバーの所有権の適切な管理については誰もが完全に正しいですが、特定のサンプルを簡単に作成して、動的メンバーを完全に使用しないようにすることができます。

クラスA

class A {
    public:
        A(int x);
        int x;
};

A::A(int x) 
   : x(x)
{
}

クラスB

class B {
    public:
        B(int x);
        A a;
};

B::B(int x) 
    : a(x) 
{
}

メインプログラム

int main() {
    vector<B> vec;

    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i));
    }

    cout << "adding complete" << endl;

    for(int i = 0; i < 10; i++) {
        cout << "x = " << vec[i].a.x << endl;
    }

    return 0;
}

結論 正当な理由がない限り、動的割り当てを使用しないでください。動的割り当ては、スマート ポインター3 つのルールを精力的に実践するクラスなどの含まれる変数によって存続期間が保護されます。

于 2012-11-12T19:30:54.577 に答える