2017-11-30 3 views
0

I持って、次のマッパークラス:C++で参照によって返されたパラメータに物事を累積するのはいいですか?

std::map<uint32_t, uint32_t>& ObjectMapper::getMappingForObject(
     Object* object) { 
    const auto mappingTableIterator = m_objMapping.find(object); 
    if (mappingTableIterator == m_objMapping.end()) { 
     auto it = m_objMapping.emplace(object, 
              std::map<uint32_t, uint32_t>()); 
     return it.first->second; 
    } 
    return mappingTableIterator->second; 
} 

がそれでは呼び出し側がこれを行うことができます:

std::map<uint32_t, uint32_t>& mappingTable = 
      objMapper.getMappingForObject(object); 

そして、上に行くと追加し、実装がこのようなものである

class ObjectMapper { 
public: 
    std::map<uint32_t, uint32_t>& getMappingForObject(
      Object* object); 

private: 
    std::unordered_map<Object*, std::map<uint32_t, uint32_t>> m_objMapping; 
}; 

/mappingTableのものを削除する。

これはC++の良いパターンですか?私はこれが所有権を渡すために参照出力パラメータを使用していると感じていますが、それは匂いですが、わかりません。より良い方法がありますか?

+2

あなたの 'getMappingForObject'はマップの' operator [] 'です... –

+2

あなたは所有権を渡さなかったので、あなたの' unordered_map'は生のポインタしか持っていません。あなたは出力パラメータを持っていません。何かが "コードのにおい"であるかどうかは、非常に意見があります。 –

+0

「それはにおいですか?」と尋ねるのは正確にはどういう意味ですか?おそらくタイトルはあまり慣れないべきです。 –

答えて

0

関数を簡単に書き直すと、呼び出し元が後で使用するために結果を格納せず、マップの変更によって参照が無効になることがわかっている限り、正しいことが示されます。さんが戻ってそれに取得してみましょう...あなたの元の関数のように書き換えることができ

:一般的なルールとして

std::map<uint32_t, uint32_t>& ObjectMapper::getMappingForObject(Object* object) 
{ 
    if (m_objMapping.count(object) == 0) 
    { 
     // a new object, remove test if nothing special needs to be done. 
    } 
    return m_objMapping[object]; 
} 

、あなたはObjectMapperオブジェクトは、呼び出し元の範囲よりも長生きすると仮定すべきです。返されるリファレンスは、独自のオブジェクトデータからのものです。したがって、呼び出し元がルールに従う限り、生涯の問題はありません。

返されたマップを長時間(数ミリ秒より長く)使用する場合:またはがマルチスレッドアプリケーションに含まれている場合は、代わりにマップのコピーを使用することをお勧めします。データ構造がロックされている時間を最小限に抑え、マップデータの変更を「トランザクション化」します。

関連する問題