2016-07-27 4 views
-1

У меня есть unordered_map типа <const char *, std::list<void *>>, и у меня есть большой список значений, которые я выполняю, чтобы проверить, есть ли соответствие в каком-либо состоянии. Если есть совпадение, я хочу добавить указатель на определенное значение в std :: list по индексу значения.Инициализация std :: list элементов std :: unordered_map

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 тип пользовательского списка, который я итерация правильно, если нетрадиционно, чтобы получить все константные строки символ * C, чтобы использовать в качестве потенциальных ключей , если есть соответствие при условии.

Однако gdb показывает, что std :: list никогда не инициализируется для интересующего ключа, и я думаю, что это имеет какое-то отношение к моему страху инициализации std :: list для каждого значения handler_name и одновременно необходимо проверить запись, чтобы увидеть, существует ли список до добавления нового значения.

Каков наилучший способ сделать правильную инициализацию в этом случае?

+3

отправьте сообщение [MCVE] –

+0

@ m.s.: кроме «условия», этот вопрос выглядит вполне полным для меня. У ОП явно есть проблема понимания «инициализации» и не знает разницы между ссылками и значениями. – 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,

Я понятия не имею, что это значит. Выражение 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 ıA копию значения в карте, так что если 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 s является инициализированы, как только добавляется запись в 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)

 Смежные вопросы

  • Нет связанных вопросов^_^