【问题标题】:STL map - insert or updateSTL 映射 - 插入或更新
【发布时间】:2022-03-17 18:18:25
【问题描述】:

我有一个对象映射,我想更新映射到键的对象,或者创建一个新对象并插入到映射中。更新由一个不同的函数完成,该函数接受一个指向对象的指针 (void update(MyClass *obj))

在地图中“插入或更新”元素的最佳方式是什么?

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    operator[]   

    【讨论】:

    • 这可以产生优雅的代码,如果你想插入一个默认的MyClass 对象,然后更新它。如果需要插入非默认对象,或者不更新插入的值,Charles 的方案可能会更好。
    • update(my_map[key])?这也意味着你总是update(从问题中不清楚)。
    • 如果密钥不存在怎么办?
    • @Konrad:将插入并返回一个默认构造元素。这可能是也可能不是所需的语义,这取决于一切是如何工作的。
    【解决方案2】:

    使用类似于以下 sn-p 的内容:

    std::map<Key, Value>::iterator i = amap.find(key);
    
    if (i == amap.end())
        amap.insert(std::make_pair(key, CreateFunction()));
    else
        UpdateFunction(&(i->second));
    

    如果您想测量可能会提高性能的东西,您可能需要使用 .lower_bound() 来查找条目的位置,并在需要插入新对象的情况下将其用作插入提示。

    std::map<Key, Value>::iterator i = amap.lower_bound(key);
    
    if (i == amap.end() || i->first != key)
        amap.insert(i, std::make_pair(key, CreateFunction()));
                                           // Might need to check and decrement i.
                                           // Only guaranteed to be amortized constant
                                           // time if insertion is immediately after
                                           // the hint position.
    else
        UpdateFunction(&(i->second));
    

    【讨论】:

    • 我认为如果 i 不等于 amap.begin(),您实际上需要减少它。因此,一个明显的问题是:如何暗示它应该被插入到第一个位置?我想它适用于无提示版本:/
    • 是的,这有点棘手。如果提示紧接在插入位置之后,则实现可以提高效率。这似乎更整洁......这就是它的修复方式:open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233
    【解决方案3】:

    类似:

    map<int,MyClass*> mymap;
    map<int,MyClass*>::iterator it;
    
    MyClass* dummy = new MyClass();
    mymap.insert(pair<int,MyClass*>(2,dummy));
    
    it = mymap.find(2);
    update(it.second);
    

    这里有一个很好的参考link

    【讨论】:

    • 如果你要走那条路:MyClass&amp; obj = mymap[2]; update(&amp;obj);
    • 是的,但是使用 [] 你应该知道如果对象不存在,它会创建一个新对象(导致第二个是空指针)
    • 没有。如果键不存在,则插入一个,然后返回对它的引用。因此,只要有内存,就可以保证获得一个有效的对象。即使那不是行为,它肯定不会产生无效的引用。在这种情况下更有可能出现异常。
    • @Dennis 是的,它会创建一个新对,但值 (it.second) 是指向尚未设置的 MyClass 对象的指针。
    • 哦,您正在使用动态对象。是的,这确实有所作为。不过,你不应该那样做。它充满了问题。
    【解决方案4】:

    operator[] 已经可以满足您的需求。详情请见the reference

    【讨论】:

    • 奇怪的是,参考是错误的。参考资料说 operator [] 相当于插入,但是 m.insert(std::make_pair("a", "1")); m.insert(std::make_pair("a", "2"));不更新 m。 m["a"] 保持 "1" 。 m["a"] = "2" 将更新 m。其中:map m;
    【解决方案5】:

    insert 的返回值是“一对由插入元素(或阻止插入的元素)的迭代器和表示插入是否发生的布尔值组成。”

    因此你可以简单地做

    auto result = values.insert({ key, CreateFunction()});
    if (!result.second)
        UpdateFunction(&(result.first->second));
    

    注意: 由于您的问题涉及原始指针,并且您说您希望 Update 函数获取指针,因此我在我的 sn-p.xml 中做出了这个假设。假设 CreateFunction() 返回一个指针,而 UpdateFunction() 需要一个指针。

    我强烈建议不要使用原始指针。

    【讨论】:

      【解决方案6】:

      在 C++17 中,函数 insert_or_assign 如果不存在则插入,如果存在则更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-03
        • 1970-01-01
        • 2018-08-01
        • 2013-05-20
        • 1970-01-01
        • 2011-05-29
        • 1970-01-01
        相关资源
        最近更新 更多