改善管理STD :: MAP对象的函数的执行时间,如何?
我有一个标题文件 header.hpp
在其中声明此功能:
#ifndef COMMON_HPP
#define COMMON_HPP
#include <string>
#include <map>
extern std::string func( const std::map <std::string, std::string>& generic_map, const std::string& feat_string )
#endif
并且该函数是在 .cpp
文件中定义的:
#include "header.hpp"
#include <string>
#include <map>
std::string func( const std::map <std::string, std::string>& map_s, const std::string& str )
{
if( map_s.find( str ) == map_s.end() )
{
throw std::runtime_error( "Error!" );
}
return map_s.at( str );
}
基准测试注册的执行时间 292 292 NS 在2684415迭代中。您知道是否有任何方法可以改善功能以使其更快?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
鉴于代码有多小,实际上您可以对其进行很多更改,但是有几个:
使用
iterator
map :: find :: find()返回,您不需要调用
map :: at()
之后。实际上,当您真的只想执行1次时,您实际上正在执行相同的搜索。返回对找到值的引用,以避免制作其副本(
map :: at()
无论如何还是返回引用)。您投掷的例外将确保返回的参考永远不会无效。如果您不需要
MAP
要排序,请使用std :: unordered_map
,它通常比> std :: map 用于插入和查找。
尝试以下操作:
话虽如此,如果您不介意投掷哪种错误消息,则可以用
map :: find()
用map :: at(),因为
map :: at()
抛出自己的std :: out_of_range
如果找不到键(这是map ::的全部目的) at()
vsmap ::操作员[]
),例如:Given how small the code is, there is really not many changes you can make to it, but there are a few:
use the
iterator
thatmap::find()
returns, you don't need to callmap::at()
afterwards. You are actually performing the same search 2 times, when you really want to perform it only 1 time.return a reference to the found value, to avoid making a copy of it (
map::at()
returns a reference anyway). The exception you are throwing will ensure the returned reference is never invalid.If you don't need the
map
to be sorted, usestd::unordered_map
instead, which is usually faster thanstd::map
for inserts and lookups.Try this:
That being said, if you don't mind what kind of error message is thrown, you can replace
map::find()
withmap::at()
, sincemap::at()
throws its ownstd::out_of_range
exception if the key is not found (that is the whole purpose ofmap::at()
vsmap::operator[]
), eg:首先,它返回
std :: String
而不是const std :: string&amp;
,它是慢的(涉及复制)。同样,当前编译器中的例外非常昂贵。他们围绕他们的一种可能的方法是返回
const std :: string*
和返回nullptr
在没有找到元素的情况下(还删除了双重查找):高级技术正在继续通过样式,可以进一步优化您的代码(并为您节省分支)。在这种情况下,您没有返回某些内容,而是通过结果应完成的操作:
用法:
这就像您拥有自己的控制结构一样。当然,您可以使返回类型与void不同(如果您想“隧道”找到
(elem)
和notfound()
)的结果。如果您愿意,可以在多个函数的调用中共享错误处理程序(在这种情况下,您将其存储在变量中,例如const auto onnotfound = [&amp;]()()(){ /* .. 。 */}; )。当然,当您进行优化时,您可能会将lambda的捕获限制为必要的。
First, it returns
std::string
instead ofconst std::string&
, which is slow (involves a copy).Also, exceptions in current compilers are very expensive. A possible way around them is to return a
const std::string*
and returnnullptr
in case element is not found (also removed double lookup):An advanced technique is continuation passing style, which can further optimize your code (and save you a branching). In this case, instead of returning something, you pass what should be done with the result:
Usage:
This is like if you had your own control structures. Of course, you could make the return type different from void (in case you'd like to 'tunnel' the result of
found(elem)
andnotFound()
). If you'd like, you can share e.g. the error handler among multiple calls to the function (in which case, you store it in a variable, likeconst auto onNotFound = [&]() { /* ... */ };
). Of course, when you're optimizing, you might limit the capture of the lambda to what's necessary.您正在向地图上进行两个查找以获取所寻求的元素:
这是一个立即的改进:
您可以做出的另一个改进是使用a std :: unordered_map 而不是
std :: map
。如果您不需要按任何排序或一致的顺序列举地图中的密钥,则应使用unordered_map,这是插入和查找的o(1)。有序的地图可能具有O(LG N)运行时,用于插入和查找。 (即集合的哈希表与二进制树实现)。std :: unordered_map
和std :: map
具有几乎相同的接口,因此这是一个简单的替换。You're doing two lookups into the map to get the element you seek:
Here's an immediate improvement:
The other improvement you can make is to use a std::unordered_map instead of
std::map
. If you don't need to enumerate keys in the map in any sorted or consistent order, you should use unordered_map, which is O(1) for insertion and lookup. The ordered map will likely have O(lg N) runtime for insertion and lookup. (i.e. hash table vs binary tree implementations for the collections).std::unordered_map
andstd::map
have near identical interfaces, so it's an easy drop-in replacement.