繁体   English   中英

std::map insert() 提示位置:c++98 和 c++11 的区别

[英]std::map insert() hint location: difference between c++98 and c++11

cplusplus 在 map::insert() 上的条目上,我读到了一个可以作为提示添加的函数的位置,即“如果position指向将插入元素之前的元素,函数将优化其插入时间”对于 C++ 98,而对于 c++11,优化发生“如果position指向将跟随插入元素的元素(或指向末尾,如果它是最后一个)”。

这是否意味着以下形式的代码片段的性能(在我正在处理的遗留代码中很丰富,并以Scott Meyer的“有效 STL”,第 24 项为模型)在切换到 C++ 时受到影响11 兼容的编译器?

auto pLoc = someMap.lower_bound(someKey);
if(pLoc != someMap.end() && !(someMap.key_comp()(someKey, pLoc->first)))
    return pLoc->second;
else
    auto newValue = expensiveCalculation();
    someMap.insert(pLoc, make_pair(someKey, newValue));  // using the lower bound as hint
    return newValue;

改进此模式以与 C++11 一起使用的最佳方法是什么?

C++98 规范是标准中的一个缺陷。 请参阅LWG 问题 233N1780 中的讨论。

回想一下, lower_bound返回一个迭代器到第一个键不小于指定键的元素,而upper_bound返回一个迭代器到第一个键大于指定键的元素。 如果在容器中没有与指定键等效的键,则lower_boundupper_bound返回相同的东西 - 一个迭代器,指向该键之后的元素(如果它在映射中)。

因此,换句话说,您当前的代码在 C++11 规范下已经可以正常工作,而实际上在 C++98 的有缺陷规范下是错误的。

是的,它会影响复杂性。 给出正确的提示将使insert()具有分摊常数复杂度,而给出和不正确的提示将迫使地图从头开始搜索位置,给出对数复杂度。 基本上,无论您的地图有多大,一个好的提示都会使插入在恒定时间内发生; 带有不好的提示,在较大的地图上插入会更慢。

显然,解决方案是使用upper_bound而不是lower_bound来搜索提示。

我认为正确的 C++11-style 提示插入可能如下:

iterator it = table.upper_bound(key);   //upper_bound returns an iterator pointing to the first element that is greater than key
if (it == table.begin() || (--it)->first < key) {
    // key not found path
    table.insert(it, make_pair(key, value));
}
else {
    // key found path
    it->second = value;
}

工作 lambda 函数的快照供您参考。 注意: m_map不应为空。 如果地图为空,则很容易知道在哪里添加元素。

    auto create_or_get_iter = [this] (const K& key) {

        auto it_upper = m_map.upper_bound(key);
        auto it_effective = it_upper == m_map.begin() ? it_upper : std::prev(it_upper);
        auto init_val = it_effective->second;

        if (it_effective == m_map.begin() || it_effective->first < key) {
            return m_map.insert(it_effective, std::make_pair(key, init_val));
        } else {
            it_effective->second = init_val;
            return it_effective;
        }

    };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM