2011-06-21 9 views
1

私はC++で始まったばかりです。auto_mapというテンプレートクラスを作成する際にいくつかの問題があります。std :: mapは、オブジェクトではなくポインターを格納する必要があります。私はこのように使用std :: mapにポインタを格納するテンプレートクラスのコピーコンストラクタを書くには?

std::map<K*, V*, cmp> m; 

::のような

何か

auto_map<std::string, std::string> t; 
t.insert(new std::string("A"), new std::string("B")); 

CPMは次のとおりです。

struct cmp 
{ 
    bool operator()(K *a, K *b) { return *a < *b; } 
    bool operator== (K *a) { return (*a); } 
}; 

挿入する前に、すべての重複の挿入機能を検索:

void insert(K* k, V* v) 
{ 
    for (typename std::map<K*, V*, cmp>::iterator i=m.begin(); i!=m.end(); ++i) 
    { 
    if ((*k) == (*(*i).first)) 
    { 
     delete (*i).first; 
     delete (*i).second; 
     m.erase(i); 
    }   
    } 
    m.insert(std::make_pair(k,v)); 
} 

とコンストラクタ:

auto_map(){} 
~auto_map() 
{ 
    for (typename std::map<K*, V*, cmp>::iterator i=m.begin(); i!=m.end(); ++i) 
    { 
    delete (*i).first; 
    delete (*i).second; 
    m.erase(i); 
    } 
} 

これらが正常に動作しているが、今、あなたは、おそらくアイデアを得ます。 ここで私はそれほど確実ではないという疑問があります。

どのようにコピーコンストラクタを書くのですか?

auto_map (auto_map& original) 
{ 
    for (typename std::map<K*, V*, cmp>::iterator i=original.m.begin(); i!=original.m.end(); ++i) 
    { 

    // what goes in here that will call each objects copy-constructor? 
    // how not to get complained about invalid conversions?... 

    // K newk = (*(*i).first); 
    // V newv = (*(*i).second); 
    // m.insert(std::make_pair(newk, newv)); 
    // gives compiler error: cannot convert ‘const CntInteger’ to ‘CntInteger* const’ in initialization 
    // cannot convert ‘const CntInteger’ to ‘CntInteger*’ in initialization 


    } 
}; 

お返事ありがとうございました!

+0

なぜあなたはデフォルトのコンストラクタでそのループを持っていますか?確かに 'm'は空になりますか? –

+0

私は彼がなぜこれをしたいのだろうと思っているのだろうか?ディープコピーセマンティクスを使用する場合は、オブジェクトへのポインタではなくオブジェクトを使用してください。あなたは通常の方法と同じだけ多くのコピーコンストラクタとコピー操作を行います。 std :: mapをレイヤー化する際に重大な間違いをしたことを心配する必要はありません。また、多くのオブジェクトを割り当てる必要がないため、処理速度が向上する可能性があります。オブジェクトのstd :: pairの割り当ては1つの割り当てです。ポインタのstd :: pairの割り当ては、std :: pairのための1つのallocとメンバーのための1つです。 –

+0

ここであなたの本当のユースケースは何ですか? 'std :: string'はすでにメモリ管理されています。速度が心配な場合は、' std :: unordered_map 'を使うだけです。それはオプションですか? –

答えて

0

私はあなたがやろうとしているものの有用性を疑うが、ここに行く:

auto_map (auto_map& original) 
{ 
    K * kp = 0; 
    V * vp = 0; 
    try 
    { 
     for (typename std::map<K*, V*, cmp>::iterator i=original.m.begin(); 
      i!=original.m.end(); 
      ++i, kp=0, vp=0) 
     { 
      kp = new K(*(i->first)); 
      vp = new V(*(i->second)); 
      m[kp] = vp;     
     } 
    } 
    catch(...) 
    { 
     delete kp; 
     delete vp; 

     // write a destroy function that does the same thing 
     // as your destructor does now 
     destroy(); 
     throw;  
    } 
} 
+5

このソリューションは 'K'と' V'をスライスします。 OPがコンテナのディープコピーセマンティクスを望んでいる場合、唯一の解決策は 'K'と' V'がクローン可能であることを要求することです。 – Lambdageek

+1

それは価値があるため、例外的に安全ではありません。 –

1

タイトルからあなたのリテラル質問に答えるために:あなたは、既存のクラステンプレートstd::mapのための新たなコピーコンストラクタを記述することはできません。

次に、あなたが本当に(考えるstd::shared_ptrの追加メモリ管理の考慮事項を使用してコンテナのために再度検索を(n個のログを記録)Oとのマップの全体(バイナリツリー)構造を実装することを確信していますカスタムの削除者を持つオブジェクト)?単にshared_ptrさんを地図に載せるのはなぜですか?

std::map<std::shared_ptr<Key>, std::shared_ptr<Value>> 

更新:あなたはBoost's pointer containersを使用してもらえますか?あるいは、あなたの値がポインタである必要がありますか? How aboutboost::ptr_unordered_map<std::string, T>の値がT*

+0

彼のコードから、主な作業を行うために内部的にstd :: mapを使用していることは明らかです。 –

+0

@ニコール:確かに、OPの見た目では、キーと価値のあるメンバーをスマートなポインタのように扱おうとしています。私は主に、混乱した質問のタイトルと実装の試行の間に、これが標準的なライブラリ構造を使用して非常に簡単に解決できる可能性があるかどうかを調べることを試みています。 –