【问题标题】:Does std::map support caching?std::map 是否支持缓存?
【发布时间】:2013-05-04 10:46:59
【问题描述】:

例如:

code1:

if((iter = map.find(key)) != map.end()) {
    return iter->second;
}
return 0;

代码2:

if(map.count(key) > 0) {
    return map.at(key);
}
return 0;

code2 要简单得多,但 map.count()map.at() 都需要 O(logn) 时间。 std::map 是否提供了将最后一个搜索项存储在缓存中并加快搜索相同项的功能,还是仅在整个地图中执行第二次搜索?

【问题讨论】:

    标签: c++ map stl


    【解决方案1】:

    它在整个地图中进行搜索,没有进行缓存 - 或者至少,标准没有强制要求,我会说没有实现这样做,因为 所有 这样的客户实现必须为每次插入/删除后更新缓存信息的可能不需要的开销付费。

    第一种方法是确定键/值对是否包含在映射中的惯用方法(请注意应该使用operator -> 而不是operator .,因为您从find() 得到的是一个迭代器,并且对iter 的赋值应该在if 条件之外):

    auto iter = map.find(key);
    if (iter != map.end()) {
        return iter->second;
    }
    

    【讨论】:

    • +1 虽然将第一个示例中的条件分成两行会更清楚 IMO。
    • @AndyProwl:建议的检索函数与 std::map::at 的作用相同(C++11 起)
    • @dalle:嗯,你是对的。我不知道我怎么能忽略它,谢谢你提到它。我将删除那部分
    • @rhalbersma:并不是说我敢反对 Sutter 和 Alexandrescu,但这主要取决于我要说的用户的要求,以及您如何定义先决条件。这就是标准库提供投掷和非投掷替代方案的原因。
    • 是的,我现在明白了,这就是为什么at() 具有元素存在的前提条件。原始的 find()operator[] 没有。 (我在您更新期间写了我已删除的评论)。
    【解决方案2】:

    不,据我所知,没有任何 C++ 标准库实现使用缓存。 C++11 要求容器对于多个阅读器是线程安全的。并且为了实现对缓存的访问需要同步。这将导致速度损失,即使您不想要它。 C++ 的一个标准做法是,您不应该为您不明确需要或不想要的任何东西付费。

    【讨论】:

    • 标准是否保证 std::map 对多个读取器(假设没有写入器)是线程安全的?否则这个论点毫无意义。
    • @Zarat:根据 C++11 是的。
    • 所以结论是,由于标准要求这种情况下的线程安全,缓存也需要是线程安全的,这会减慢不想要/不需要它的调用者。
    • @Zarat:澄清了我所说的“不适合多线程”。
    【解决方案3】:

    可以,但据我所知没有一个。惯用的解决方案是 因此使用变量:

    auto results = myMap.find( key );
    return results == myMap.end()
        ? NULL
        : &results->second;
    

    简短、干净且易于理解。 (并且它避免了使推理程序正确性变得如此困难的多次返回。)

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多