假设我们有一个昂贵的函数映射string
到int
,并希望将结果缓存到地图中。
最简单的代码是
int mapStringToIntWithCache(std::string const& s) {
static std::unordered_map<std::string, int> cache;
if (cache.count(s) > 0) return cache[s];
else return cache[s] = myExpensiveFunction(s);
}
但这有两次查找。
因此我倾向于写这个
int mapStringToIntWithCache(std::string const& s) {
static std::unordered_map<std::string, int> cache;
size_t sizeBefore = cache.size();
int& val = cache[s];
if (cache.size() > sizeBefore) val = myExpensiveFunction(s);
return val;
}
这只有一次查找,但看起来有点笨拙。还有更好的方法吗?
答案 0 :(得分:7)
只需使用(\w+)(?:\:)(.*),
$1:$1
方法:
std::map::emplace()
答案 1 :(得分:1)
请注意@Slava的答案:如果你通过const左值引用传递参数,那么如果它是rvalue,你就不能从这个参数移动:
int i = mapStringToIntWithCache("rvalue argument here");
如果插入std::string
,则临时cache
参数将复制。
你可以使用完美转发,但是,如果你想保持参数只有std::string
类型(例如,对于字符串文字的隐式转换),那么你需要一些< em> wrapper-helper function 解决方案:
template <typename T>
int mapStringToIntWithCacheHelper(T&& s) {
static std::unordered_map<std::string, int> cache;
auto pair = cache.emplace( std::forward<T>(s), 0 );
if( pair.second )
pair.first->second = myExpensiveFunction(pair.first->first); // can't use s here !!!
return pair.first->second;
}
int mapStringToIntWithCache(const std::string & s) {
mapStringToIntWithCacheHelper(s);
}
int mapStringToIntWithCache(std::string && s) {
mapStringToIntWithCacheHelper(std::move(s));
}