質問

私は観察不思議な行動のstd::地図::clear().この方法は呼び要素のデストラクタが呼び出されると、しかしメモリがまだアクセス呼び出し後のclear().

例えば:

struct A
{
  ~A() { x = 0; }
  int x;
};

int main( void )
{
  std::map< int, A * > my_map;
  A *a = new A();
  a->x = 5;
  my_map.insert( std::make_pair< int, *A >( 0, a ) );

  // addresses will be the same, will print 5
  std::cout << a << " " << my_map[0] << " " << my_map[0]->x << std::endl;

  my_map.clear();

  // will be 0
  std::cout << a->x << std::endl;

  return 0;
}

それでは、なぜ変数 a まだアクセスの後、そのデストラクタで呼ばれていた地図::clear()?いただいた書 delete a; を呼び出した後 my_map.clear() ているのか、あるいは安全な書き込みの内容 a?

よろしくお願のために皆さまのご協力のもと、 sneg

役に立ちましたか?

解決

のstd ::マップがメモリを管理していないポインタ値によって指さ - それを自分で行うには、あなた次第です。あなたはスマートポインタを使用したくない場合は、このような汎用無料&クリア機能を書くことができます:

template <typename M> void FreeClear( M & amap ) 
    for ( typename M::iterator it = amap.begin(); it != amap.end(); ++it ) {
        delete it->second;
    }
    amap.clear();
}

そして、それを使用します:

std::map< int, A * > my_map;
// populate
FreeClear( my_map )

他のヒント

あなたがマップ(またはリスト、あるいはそのようなもの)にポインタを格納した場合のは、は、彼らは新しいを使用して作成されている場合はマップが知っていないので、ポインタを削除する責任があります、 か否か。あなたは、ポインタを使用しない場合はクリア機能のみデストラクタを呼び出します。

ああ、もう一つ:デストラクタを呼び出す(あるいは削除を呼び出す)、メモリはもうアクセスすることはできませんという意味ではありません。それだけであなたが行う場合は、ゴミにアクセスされることを意味します。

あなたはヒープメモリの一部を解放すると、

、その内容はゼロにされません。彼らは再び割り当てのために単に利用可能です。割り当てられていないメモリへのアクセスの効果が定義されていませんので、もちろんあなたは、メモリ以外のアクセスを考慮する必要があります。

実際にメモリページへのアクセスを防止することが、より低いレベルで起こる、とstdライブラリはそれをしません。

あなたが新しいとメモリを割り当てるときは、スマートポインタを使用しない限り、

、あなたは、それを自分で削除する必要があります。

すべてのコンテナに格納あなたのオブジェクトの種類と呼び、対応するコンストラクタ:内部コードは、各ノードはのようになります。

__NodePtr
{
    *next;
    __Ty    Val;
}

あなたはそれがタイプに基づいヴァルを構築してからリンクすることによって起こる割り当てるとき。似た何かます:

_Ty _Val = _Ty();
_Myhead = _Buynode();
_Construct_n(_Count, _Val);
あなたが削除すると、

それは、対応するデストラクタを呼び出します。

あなたが参照(ポインタ)を格納するとき、それはすべてのコンストラクタを呼び出しませんまた、それが破壊されます。

この最後の2ヶ月間の食べる、寝る、呼吸を図ってました。の地図配分で自分のデータとなりました。日記を無茶苦茶にしクリーナーは、そんな理由だけを強調します。

あの微妙なメリットのような場合だけコピーからデータファイルまたはソケットの地図のデータは、データ保存が存在するどのノードが存在するので図の通話malloc()を配置するノードが割り当てメモリの両方を身につけることが必要です。(通称地図[キー].最初に、地図[キー].秒)

これは、代入演算子の代わりにmemcpy()、1以下の呼び出malloc()の一することができます。

IC_CDR CDR, *pThisCDRLeafData;  // a large struct{}

    while(1 == fread(CDR, sizeof(CDR), 1, fp))  {
    if(feof(fp)) {
        printf("\nfread() failure in %s at line %i", __FILE__, __LINE__);
    }
    cdrMap[CDR.iGUID] = CDR; // no need for a malloc() and memcpy() here    
    pThisCDRLeafData  = &cdrMap[CDR.iGUID]; // pointer to tree node's data

少し注意する認識しているを指す。

  1. いませ------------malloc()、または新たにラインのコードを追加するツリーのノードとしてお呼び出malloc()の返すポインタの前に地図をmalloc()で割り当てる場所に返却からのmalloc().
  2. デバッグモードで、改めて質の追求を高めていくとしても同様の問題を抱えようとする場合free()です。このようなコンパイラの問題が少なくともMSVC、2012年にも存在し、深刻な問題となっています。
  3. 一考して"アンカー"だ。IE:でm?$($i$l$k!%いいえ対象外となります。主{}は常に安全です。

    INT _tmain(INT argc, char* argv[])    {
    IC_CDR      CDR, *pThisCDRLeafData=NULL;
    CDR_MAP     cdrMap;
    CUST_MAP    custMap;
    KCI_MAP     kciMap;
    
  4. 私の非常に良い、とても嬉しく思いる重要な地図に配置していましたが、このノードのデータを有する構造体"アンカー"。が匿名で構造体を持されているよC++(ひどいもので、恐ろしいものと判断する必要性、地図の第1回構造体会員の仕事のように匿名で構造体.非常にスリックやクリーンサイズがゼロの定されます。通しのポインタの葉の有struct、またはコピーの構造体による価値の呼び出しにより、非常に泳いでいる。オススメです。

  5. できるトラップの戻り値です。挿入するかどうかを判定しますが、既存のノードがキーを作成します。(#12のためのコードは下付き文字表記することを認めていません。すると良いのか解決します。挿入し、そうしていくべきである、ので、[]の表記になりませんmultimaps.(ことができるとされていることなんてないのではないで"a"キーはシリーズのキーと同じ値multimap)
  6. でき、き、またトラップを返します。消去ます。empty()(りんかれてい機能を必要と()の一部です。消去、せん)
  7. しかでき、キーの値およびデータ値として他のノード地図。初ます。第二に、すべてのマップにより、条約、利用のキーデータをそれぞれ
  8. で身につけ、大量の混乱およびタイピング用typedefsご図のようです。

    typedef map<ULLNG, IC_CDR>      CDR_MAP;    
    typedef map<ULLNG, pIC_CDR>     CALL_MAP;   
    typedef struct {
        CALL_MAP    callMap;
        ULNG        Knt;         
        DBL         BurnRateSec; 
        DBL         DeciCents;   
        ULLNG       tThen;       
        DBL         OldKCIKey;   
    } CUST_SUM, *pCUST_SUM;
    typedef map<ULNG,CUST_SUM>  CUST_MAP, CUST_MAP;  
    typedef map<DBL,pCUST_SUM>  KCI_MAP;
    
  9. パスへの参照地図のtypedefであり、オペレーターとして

    ULNG DestroyCustomer_callMap(CUST_SUM Summary, CDR_MAP& cdrMap, KCI_MAP& kciMap)

  10. 利用は"auto"自動可変タイプのための反復子.のコンパイルす図から指定された型の残りのために()ループ体どのような地図typedefです。でこんなにきれいなのでほとんどです。

    for(auto itr = Summary.callMap.begin(); itr!= Summary.callMap.end(); ++itr) {

  11. 定義しているマニフェストの定数を返します。消去ます。empty()より多いのでmeaningfull.

    if(ERASE_SUCCESSFUL == cdrMap.erase (itr->second->iGUID)) {

  12. この"スマートポイント"なんだこの参照カウントを覚えていをご参照カウント、もバックナンバーは、ますます明らかなのです。組み合わせること#5-#10以上に、一部のカスタマーサポートのようにします。

    #define Pear(x,y) std::make_pair(x,y) //  some macro magic
    
    auto res = pSumStruct->callMap.insert(Pear(pCDR->iGUID,pCDR));
    if ( ! res.second ) {
        pCDR->RefKnt=2;
    } else {
        pCDR->RefKnt=1;
        pSumStruct->Knt += 1;
    }
    
  13. 利用のポインタをハングを図るノード割り当てのために、IE:ないユーザポインタを指ユーザーのmalloc()編物も、潜在的に効率化および変更に使用するノードのデータなし側面の効果が楽しめます。

  14. 同じテーマに、ポインタを使用できる非常に効果的に保全の状態は次のノードとして pThisCDRLeafData ます。この関数に変異が引き起/変更する特定のノードのデータリーダー格への参照地図のに必要なのノード pThisCDRLeafData が差します。

  15. 反復子は魔法であってはいけません。やはり高価でゆっくりすてきナビゲ地図を得る値です。地図を持百万円の値として決定されたものでノードキーで約20百万円。と反復子があるんじゃないでしょうか~1000倍しています。

いてカバーします。更新の場合は、この変更又は追加の解す。私は特に楽しみをSTLのCコードです。IE:な変化を見通します。思い意味での仕事をしているとしたものであります。テレビでも展開しております。

scroll top