2016-07-27 93 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。:除了'condition'外,這個問題對我來說看起來相當完整。 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()) 

我的恐懼初始化一個std ::列表handler_name的每一個值,

我不知道這意味着什麼。如果地圖中沒有地圖,則表達式responders[handler_name]將爲該值初始化一個空的std::list。但這就是你需要發生的事情。

這完全是無稽之談:

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

首先,它評估responders[handler_name],它返回std::list對應的鍵值(創建一個空的,如果它不存在的話)。

然後它將該列表複製到名爲scripts的新對象中。

然後,如果scripts不是空它通過複製scripts(其必須是完全沒有意義的取代在映射中的值,因爲scripts Ia的地圖中的值的拷貝,因此,如果scripts是不空的,則地圖中的一個已經不是空的)。

然後最後你修改列表,scripts,這是一個局部變量,在循環的結束超出範圍的副本,所以你從不添加任何條目存儲在地圖列表中。

同時需要在添加新值之前檢查條目以查看列表是否已經存在。

你不需要那樣做。 responses[handler_name]是爲你做的。如果沒有輸入該密鑰,將會創建一個。

在這種情況下進行正確初始化的最佳方法是什麼?

不要擔心什麼,然後寫無意義的代碼來儘量避免非問題。 responses[handler_name]執行所有您需要的初始化。它會查找與該鍵相對應的列表,如果未找到列表,則會正確初始化一個空列表。

那廢話整個塊可以寫成簡單:

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*>可能甚至沒有必要,因爲任何指針將隱式轉換爲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

我的意見是關於代碼,而不是它的作者。將對象複製出容器,然後有條件地將其複製回去_is_無關緊要。這不僅僅是風格不佳,或者有點低效,它完全是多餘的,並不能解決問題。我想強調的是,不只是說「這是一個更好的方法來做到這一點」。良好的編程需要基於正確理解的清晰思考和有意識的行動,特別是在C++中。 –

1

假設你condition並非總是假的表達,...

list小號只要一個條目添加到responders地圖初始化。這就是C++:你不能有'未初始化'列表。它們完全構建,或者它們不存在。 (電文讀出上RAII

此代碼段:

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

是一個空操作。 變量是複製(價值語義!)從responders[handler_name]。如果是後者是空的,你只是拷貝回來......

也許你的意思是採取一個參考在條目列表,並添加到:

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

(注:如果每次你想知道,如果一個列表是空的,用list.empty() ......更清晰Express intent

相關問題