2012-03-26 5 views
1
struct Node 
{ 
int value 
Node* next; 
} 
typedef List Node* 

const Set operator +(const Set& a, const Set& b) 
{ 
    Set aSet; 
    List newList = mergeListsCopy(a.list, b.list); 
    aSet.list = newList; 
    return aSet; 
} 

class Set 
{ 
public: 
//method decs 
private: 
    List list; 
}; 

Set::~Set() 
{ 
    list = deleteList(list);  
} 

完全に罰金このコードの動作の内部には、mergeListsCopyは2つの単独でリンクされたリストから新しいリストを作成し、ASETのプライベート変数であるリストへのポインタをassignes。C++演算子のオーバーロードとデストラクタ

問題は、aSetが返されたときに、aSet.listが何らかの変なポイズンアドレス(この場合は0xf)です。

私はデバッガで実行したとき、オペレータのオーバーロードの範囲でSetが作成されましたが、このセットへの2つの参照もシンボルaSetを使用してローカルで作成されました。戻りが発生する前に、プログラムはデストラクタおそらく無関係のSetに対してですが、Setが1つしかないので、それは破壊されます。

私のデストラクタをコメントアウトすると、この問題は解消されます。私は何を間違えたのですか?

+0

NBの演算子メソッドは、関数呼び出しの仕事を使用する友人です。 – awiebe

答えて

3

Rule of Threeに従う必要があります。

あなたが明示的にどちらかデストラクタコピーコンストラクタまたはコピー代入演算子自分自身を宣言する必要がある場合、あなたはおそらく、明示的にそれらのすべての3つを宣言する必要があります。

一時的な無名のオブジェクトは、プログラムの実行とするとき、それらの一時的なオブジェクトは、それはあなたをいじり終わるデストラクタの呼び出しによって破壊され得るの過程で(コピーコンストラクタを生成し、暗黙のコンパイラを呼び出すことによって)に作成されます可能性が最も高いですリンクされたリスト。

+0

私はデストラクタを持っていれば、私もコピーコンストラクタを提供しない限りうまくいきませんか?よくわかりません。私は既定のコンストラクタを指定したことにも言及すべきだったと思います。Set.listをNULLに設定するだけです。 – awiebe

+0

実際には、** Set ofとNodeの両方のクラスに** Rule of Three **を適用する必要があります(上記のBig 3のうち自分自身を宣言する必要があると思います)。ここに見られる問題は、3つのルールを 'Set'クラスに適用しないことによるものです。 –

+1

@awiebe:コピーコンストラクタを用意していません。コピーコンストラクタは一時オブジェクトの作成中にポインタの浅いコピーを作成します(値渡しなど)。これはデストラクタへの呼び出しでさらに破棄され、実際のオブジェクトを無効にしてぶら下がりポインタにします。招待されたポインタのディープコピーを作成するコピーコンストラクタを用意する必要があります。 –

関連する問題