2016-07-27 18 views
-1

私は型が<const char *, std::list<void *>>のunordered_mapを持っており、ある条件で一致するかどうかを調べるために反復処理している値の大きなリストを持っています。一致するものがあれば、特定の値へのポインタを値のインデックスのstd :: listに追加したいと思います。std :: unordered_mapのstd :: list要素を初期化する

const char *handler_name = NULL; 
while (handler_name = all_handlers->get(), handler_name) 
{ 
    if (condition) 
    { 
     //Add pointer element to every event handler it registers 
     std::list<void *> scripts = responders[handler_name]; 
     if (scripts.size() == 0) 
     { 
      responders[handler_name] = scripts; 
     } 
     scripts.push_back(static_cast<void *> (L)); 
     active_states[static_cast<void *> (L)] = 1; //set to active so we only delete it once 
    } 
    handler_name = NULL; 
} 

これらは私の変数宣言は、以下のとおりです。

private: 
    std::unordered_map<const char*, std::list<void *>> responders; 
    std::unordered_map<void *, int> active_states; 

all_handlersは、潜在的なキーとして使用するためのconstのchar *のC文字列のすべてを取得するために従来にない場合、私は、正確に反復処理していますカスタムリストタイプです条件に一致するものがあるかどうか。

しかし、gdbはstd :: listが決して重要なキーのために初期化されていないことを明らかにしています。また、handler_nameのすべての値に対してstd :: listを初期化するという気になる新しい値を追加する前にリストがすでに存在するかどうかを確認する必要があります。

この場合、適切な初期化を行う最良の方法は何ですか?

+3

[MCVE] –

+0

@ m.sを投稿してください。: '条件 'とは別に、この質問は私にはかなり完成しているようです。 OPは明らかに「初期化」を理解する上で問題があり、参照と値の違いは分かりません。 – xtofl

+1

完了していません。 'all_handlers'とは何ですか? 'const char *'の値はどこから来ますか? OPは、同じ内容の文字列リテラルが '=='を使って等しいとみなしていると仮定していますか?ここではいくつかの前提があります。 –

答えて

0
const char* handler_name = NULL; 
while (handler_name = all_handlers->get(), handler_name) 

これはループを記述するための慣用的な方法ではありません!。実際にはそれは非常に変です。

は、より従来のアプローチを検討してください。

const char* handler_name = NULL; 
while ((handler_name = all_handlers->get())) 

(二重括弧は===間の可能な混乱についての警告を発行するいくつかのコンパイラを防ぐために必要です)。

またはその代わりにforを使用しては:

for (const char* handler_name = all_handlers->get(); handler_name; handler_name = all_handlers->get()) 

HANDLER_NAMEのすべての値のためのstd ::リストを初期化する私の恐怖、

私はこれが何を意味するのか見当がつかない。 responders[handler_name]という式は、すでにマップに値が1つもない場合は、その値の空のstd::listを初期化します。しかし、それはあなたが必要とするものです。

これはナンセンスである。

std::list<void *> scripts = responders[handler_name]; 
    if (scripts.size() == 0) 
    { 
     responders[handler_name] = scripts; 
    } 
    scripts.push_back(static_cast<void *> (L)); 

まずそのキー(そこに既に存在しない場合は空の作成)に対応std::listを返す、responders[handler_name]を評価します。

次に、そのリストをscriptsという新しいオブジェクトにコピーします。 scriptsが空ではないので、もしscriptsは、マップ内の値のコピーをイアため

そしてscripts場合、完全に無意味である必要がありscriptsを(コピーすることによってマップの値を置き換えることが空でありません地図のものはすでに空ではない)。

その後、最終的に、あなたはループの最後でスコープ外となるので、あなたは、マップに格納されたリストにエントリを追加したことがないローカル変数である、scripts、リストのコピーを変更します。

と同時に、新しい値を追加する前にリストがすでに存在するかどうかを確認する必要があります。

あなたはそうする必要はありません。 responses[handler_name]あなたのためにそれを行います。そのキーのエントリがない場合、そのキーが作成されます。

この場合、適切な初期化を行うにはどうすればよいでしょうか?

何も心配するのをやめ、非問題を回避しようとする無意味なコードを書き留めてください。 responses[handler_name]は、必要なすべての初期化を実行します。そのキーに対応するリストを探し、リストが見つからなければ空のものが適切に初期化されます。ナンセンスの全体のチャンクは単にのように書くことができることを

:任意のポインタは、暗黙的にvoid*に変換されますので、

responses[handler_name].push_back(static_cast<void *> (L)); 
    active_states[static_cast<void *> (L)] = 1; //set to active so we only delete it once 

static_cast<void*>はおそらく、さえ必要ありません。あなたは変換についてより明確にしたい場合は、それらを保つことができますが、私は単純に記述します。

for (auto handler_name = all_handlers->get(); handler_name; handler_name = all_handlers->get()) 
{ 
    if (condition) 
    { 
     //Add Lua state to every event handler it registers 
     responses[handler_name].push_back(L); 
     active_states[L] = 1; //set to active so we only delete it once 
    } 
} 

これは、はるかに簡単はるかに短い、とそうでない問題を解決するための混乱のコードが含まれていません存在する。

+0

あなたが書いているのは真実ですが、個人的には私はその言葉によって少し侮辱されているように感じます。 – xtofl

+1

@xtofl私はしません。コードは、客観的にナンセンスであるか、少なくとも無意味に難読化されている可能性があります。もしそうなら、それはそのままの状態で述べるべきです。ここには不快感や個人的なものは何もありません。そして、誰かが持つ可能性のある、そして誤解された感情的な反応のために、子供の手袋を弾くことには意味がありません。とにかく、彼らが望むならば、彼らは文句を言わせ、著者はそれを議論することができます。 –

+0

私のコメントはコードに関するものであり、著者のコメントではありません。コンテナからオブジェクトをコピーし、それを条件付きで再びコピーします。それは単に貧弱なスタイルではなく、少し非効率的であり、完全に冗長であり、問​​題の解決には貢献しません。私はそれを強調したいと思っただけではなく、 "ここでそれを行うより良い方法"と言う。良いプログラミングには、明確な思考と、特にC++の適切な理解に基づいた意図的な行動が必要です。 –

1

...あなたのconditionは、常に偽の表現ではないと仮定すると

あなた listとすぐエントリーが respondersマップに追加されるように初期化されています。それはC++です:あなたは「初期化されていない」リストを持つことはできません。それらは完全に構築されているか、存在していません。 (Readupは RAII上)

このコード:

std::list<void *> scripts = responders[handler_name]; 
    if (scripts.size() == 0) 
    { 
     responders[handler_name] = scripts; 
    } 

は何もしません。 scripts変数は、responders[handler_name]からとコピーされた(値の意味!)です。

auto & scripts = responders[handler_name]; 
scripts.push_back(static_cast<void *> (L)); 

(注:後者が空だった場合、あなただけの

は、おそらくあなたがに にエントリ内のリストを参照を取り、それに追加することを意味...戻ってそれをコピーしています:リストが空の場合、すべてはあなたが知りたい場合は、より明確list.empty()を...使用Express intent

関連する問題