map::count 后跟 map::operator[] 的效率
Efficiency of map::count followed by map::operator[]
有一种已知的问题,当映射包含一些元素并且需要访问该元素时,虽然 "element not found" 情况更倾向于通过 if-check 来处理,但仍然缺乏轻松 "please give me access to the element mapped at given key, tell me by some meaningful value that it doesn't exist, and let me access it otherwise".
的标准方法
我的目标是:我需要一个干净、简单的方法,代码看起来不错,可读性强,当然还有效率。这是 "official" 的方法:
map<int, vector<Command> > m;
map<int, vector<Command> >::iterator i = m.find(required_key);
if ( i == m.end() )
error_not_found();
i->second.SetCode(x);
这是我使用的,并且由于可读性而更喜欢 - 我的问题是:这种方法相对于上面的官方方法效率有多低:
map<int, vector<Command> > m;
if ( !m.count(required_key) )
error_not_found();
m[required_key].SetCode(x);
明显的效率损失是查找必须完成两次,而在 "official" 代码中,它只完成一次。对于大型地图上的许多访问,这将是显而易见的。另请注意,尽管 "official" 代码的可读性可能较低,但它仍然广为人知,并且它也适用于只读地图。 C++11s auto
可能有助于提高可读性。
您的方法查找两次,而官方方法只查找一次。
如果 error_not_found();
抛出,您可以改用 std::map::at
,当找不到密钥时抛出并且只有:
m.at(required_key).SetCode(x);
您仍然可以编写辅助函数来增加可读性并保持性能:
template<typename Map, typename Key>
auto value(Map& m, const Key& key)
{
auto it = m.find(key);
return it == m.end() ? nullptr : std::addressof(it->second);
}
然后
std::map<int, Command> m;
auto* command = value(m, required_key);
if (command == nullptr) {
return error_not_found();
}
command->SetCode(x);
有一种已知的问题,当映射包含一些元素并且需要访问该元素时,虽然 "element not found" 情况更倾向于通过 if-check 来处理,但仍然缺乏轻松 "please give me access to the element mapped at given key, tell me by some meaningful value that it doesn't exist, and let me access it otherwise".
的标准方法我的目标是:我需要一个干净、简单的方法,代码看起来不错,可读性强,当然还有效率。这是 "official" 的方法:
map<int, vector<Command> > m;
map<int, vector<Command> >::iterator i = m.find(required_key);
if ( i == m.end() )
error_not_found();
i->second.SetCode(x);
这是我使用的,并且由于可读性而更喜欢 - 我的问题是:这种方法相对于上面的官方方法效率有多低:
map<int, vector<Command> > m;
if ( !m.count(required_key) )
error_not_found();
m[required_key].SetCode(x);
明显的效率损失是查找必须完成两次,而在 "official" 代码中,它只完成一次。对于大型地图上的许多访问,这将是显而易见的。另请注意,尽管 "official" 代码的可读性可能较低,但它仍然广为人知,并且它也适用于只读地图。 C++11s auto
可能有助于提高可读性。
您的方法查找两次,而官方方法只查找一次。
如果 error_not_found();
抛出,您可以改用 std::map::at
,当找不到密钥时抛出并且只有:
m.at(required_key).SetCode(x);
您仍然可以编写辅助函数来增加可读性并保持性能:
template<typename Map, typename Key>
auto value(Map& m, const Key& key)
{
auto it = m.find(key);
return it == m.end() ? nullptr : std::addressof(it->second);
}
然后
std::map<int, Command> m;
auto* command = value(m, required_key);
if (command == nullptr) {
return error_not_found();
}
command->SetCode(x);