正在初始化 std::unordered_map 的 std::list 个元素
Initializing std::list elements of a std::unordered_map
我有一个 unordered_map 类型 <const char *, std::list<void *>>
,我有一个很大的值列表,我正在遍历以查看是否在某些条件下匹配。如果匹配,我想将指向某个值的指针附加到值索引处的 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 从未被初始化为感兴趣的键,我认为这与我害怕为 std::list 的每个值初始化 std::list 有关=30=],同时需要在添加新值之前检查条目以查看列表是否已经存在。
在这种情况下进行正确初始化的最佳方法是什么?
假设您的 condition
不是始终为假的表达式,...
您的 list
和 在条目添加到 responders
地图后立即初始化。那是 C++:你不能有 'uninitialized' 列表。它们是完全构建的,或者它们不存在。 (阅读 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!)
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())
my fear of initializing a std::list for every value of 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]
,其中 returns 对应于该键的 std::list
(如果不存在则创建一个空键)。
然后将该列表复制到一个名为 scripts
的新对象中。
然后如果 scripts
不为空,它 通过复制 scripts
替换 映射中的值( 必须 完全没有意义,因为 scripts
是映射中值的副本,所以如果 scripts
不为空,则映射中的值已经不为空)。
最后你修改列表的copy,scripts
,这是一个在循环结束时超出范围的局部变量,所以你永远不要向存储在地图中的列表添加任何条目。
and simultaneously needing to check the entry to see if the list already exists before appending a new value.
你不需要那样做。 responses[handler_name]
为您完成。如果没有该密钥的条目,将创建一个。
What is the best way to do proper initialization in this case?
不要再无所事事,然后编写无意义的代码来尽量避免非问题。 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
}
}
这更短、更简单,并且不包含用于解决不存在的问题的混乱代码。
我有一个 unordered_map 类型 <const char *, std::list<void *>>
,我有一个很大的值列表,我正在遍历以查看是否在某些条件下匹配。如果匹配,我想将指向某个值的指针附加到值索引处的 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 从未被初始化为感兴趣的键,我认为这与我害怕为 std::list 的每个值初始化 std::list 有关=30=],同时需要在添加新值之前检查条目以查看列表是否已经存在。
在这种情况下进行正确初始化的最佳方法是什么?
假设您的 condition
不是始终为假的表达式,...
您的 list
和 在条目添加到 responders
地图后立即初始化。那是 C++:你不能有 'uninitialized' 列表。它们是完全构建的,或者它们不存在。 (阅读 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!)
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())
my fear of initializing a std::list for every value of 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]
,其中 returns 对应于该键的 std::list
(如果不存在则创建一个空键)。
然后将该列表复制到一个名为 scripts
的新对象中。
然后如果 scripts
不为空,它 通过复制 scripts
替换 映射中的值( 必须 完全没有意义,因为 scripts
是映射中值的副本,所以如果 scripts
不为空,则映射中的值已经不为空)。
最后你修改列表的copy,scripts
,这是一个在循环结束时超出范围的局部变量,所以你永远不要向存储在地图中的列表添加任何条目。
and simultaneously needing to check the entry to see if the list already exists before appending a new value.
你不需要那样做。 responses[handler_name]
为您完成。如果没有该密钥的条目,将创建一个。
What is the best way to do proper initialization in this case?
不要再无所事事,然后编写无意义的代码来尽量避免非问题。 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
}
}
这更短、更简单,并且不包含用于解决不存在的问题的混乱代码。