2011-07-19 18 views
4

セットに挿入している間、セットは内部的にいくつかのオブジェクトを複数回削除しますか?次のプログラムのように、MyClass型のオブジェクトを2つ挿入しようとしましたが、驚いたことに、最初に値を挿入したクラスのデストラクタを2回呼び出します。私はこれの背後にある論理を理解することができません。誰もが出力にいくつかのアイデアを与えることができますか? はIで開始:3 ....挿入時のコンテナstd :: setの動作は?

挿入ヴァル:valをcalled..for 3.402000

デストラクタ:3.402000

#include<stdio.h> 
#include<stdlib.h> 
#include<set> 

using namespace std; 

    struct MyClass 
    { 
     double num; 

     ~MyClass() 
     { 
     printf("Destructor called..for val: %lf\n", num); 
     } 
    }; 

    typedef int (*fun_comp)(MyClass, MyClass); 

    int 
    comp(MyClass a, MyClass b) 
    { 
     return a.num-b.num; 
    } 

    int 
    main() 
    { 
     fun_comp fptr; 
     fptr = &comp; 
     set<MyClass, int (*)(MyClass, MyClass)> b(fptr); 

     for(int i=3; i< 5; i++) 
     { 
     printf("started with i: %d....\n\n", i); 
     { 
      MyClass m; 
      m.num=i*1.134; 
      b.insert(m); 
      printf("Inserted val: %lf\n", m.num); 
     } 
     printf("ended....\n\n"); 
     } 

     printf("Done with insert..\n");  
     return 0; 
    } 

出力を(太字ハイライト表示しました)

終了....

i:4 ....

ヴァルcalled..forデストラクタ:4.536000 <は-------これはヴァルcalled..for挿入

デストラクタ前に割り当てが解除されている理由:3.402000 < -------この値を持つオブジェクトのデストラクタへの複数呼び出し。

デストラクタを呼び出すval:4.536000 < -------- ??

デストラクタを呼び出すval:3.402000 < ------もう一度!!

挿入ヴァル:4.536000

ヴァルcalled..forデストラクタ:4.536000

が終了....

挿入して完了。..ヴァルcalled..for

デストラクタ:3.402000

デストラクタを呼び出すval:4.536000

+1

私はあなたの行動の明確な理解を持つことになります疑うように私は、「ヴァル」と一緒に、デストラクタでのthisポインタの値を印刷する印刷「ヴァル」から変更することをお勧めしたいですその後のコード。 – acm

+0

ありがとうございますが、私はそれをしましたが、アドレスが別の地域に保存されていることを除いて、有効な理由がないと結論づけることができません..出力サンプル出力はここにあります – raja

+0

はi:3 ....で始まりました 挿入された値:3.402000ヴァルcalled..for デストラクタ:3.402000 0x7fff82190a10 が終了.... は私を始めます。val called..for 4 .... デストラクタ:4.536000 0x7fff821908e0 ヴァルcalled..forデストラクタ:3.402000 0x7fff821908d0 デストラクタ呼び出されるval:4.536000 0x7fff821907d0 デストラクタが呼び出されるval:3.402000 0x7fff821907c0 挿入された値:4.536000 Deヴァルcalled..for structor:4.536000 0x7fff82190a10 が を挿入して完了....終わった...ヴァルcalled..for デストラクタ:3.402000 0x998030 ヴァルcalled..forデストラクタ:4.536000 0x998060 – raja

答えて

11

コンパレータ

int  
comp(MyClass a, MyClass b) 
{ 
    return a.num-b.num; 
} 

値によってそのパラメータをとります。これにより、余分なコピーが作成され、破棄されます。

参照渡しがうまく機能します。

+0

ありがとうございました。現在は完璧です。:) – raja

11

(const)参照を使用する比較関数を変更する

int comp(const MyClass& a, const MyClass& b) 
{ 
    return a.num-b.num; 
} 

あなたの広告が呼び出されるたびに、aとbのコピーが作成されます。これらのコピーは、終了時に破棄されます。

4

上記の点に加えて、値の一貫した順序付けが指定されていないため、比較関数は無効です。 a.num = 1かつb.num = 2の場合、comp(a、b)は真であり、aが前に来ることを意味し、comp(b、a)も真であり、bは前に来るa 。これにより、setの動作が未定義になります。

それはMyClassのため小なり演算子作成して作業を行う<>のデフォルトの比較関数を設定できるようにする方が良いでしょう: 構造体のMyClass { ダブルnumは、

~MyClass() 
    { 
    printf("Destructor called..for val: %lf\n", num); 
    } 
    bool operator < (const MyClass &rhs) const 
    { 
    return num < rhs.num; 
    } 
}; 
... 
set<MyClass> b; 
+0

hmm..point to notice !!ありがとう – raja

関連する問題