【问题标题】:Replace existing and add new entries in std::map在 std::map 中替换现有条目并添加新条目
【发布时间】:2018-12-07 07:41:26
【问题描述】:

考虑以下sn-p:

MapT map;

map["A"] = 1;
map["B"] = 2;
map["C"] = 3;
map["D"] = 4;
map["E"] = 5;

MapT mapSecond;

mapSecond["A"] = 10;
mapSecond["B"] = 20;
mapSecond["C"] = 30;
mapSecond["X"] = 4;
mapSecond["Y"] = 5;

MapT::const_iterator itSecond = mapSecond.begin();
MapT::iterator it = map.begin();

for (; itSecond != mapSecond.end(); ++itSecond)
{
    std::pair<MapT::iterator, bool> pair = map.insert(std::make_pair(itSecond->first, itSecond->second));
    if (!pair.second)
    {
        pair.first->second = itSecond->second;
    }
}

for (; it != map.end(); ++it)
{
    std::cout << it->first << " " << it->second << std::endl;
}

我假设使用从插入返回的迭代器是最有效的版本。

但一开始,我只是认为分配迭代器只能正常工作(请注意,我不再在这里取消引用迭代器)。

1.)

// assigning the dereferenced iterator (i.e.: the underlying std::pair)
// resulting in no match for binary '=' operator for const std::string
*pair->first = *itsecond;

我知道它已经过时了,因为我已经匹配了键并且只关心值。发生此错误仅是因为密钥是 const std::string 如果我没有完全失去理智:D

2.)

// assigning the iterator itself
// does not compile as long as itSecond is of type const_iterator ?
// does nothing in case itSecond is of type iterator
pair.first = itSecond;

这是我实际上不明白的事情。 std::map 中迭代器的赋值应该如何表现? 尽管我已经做了几年 C++ 编程,但我从来没有遇到过我为任何容器这样做的场景。在一些研究中,我没有找到很多关于分配迭代器的信息。

最后是否会有一种更优雅的方式来实现我想要实现的目标(使用 C++11 功能,也许是 C++14)?

【问题讨论】:

    标签: c++ stl iterator stdmap


    【解决方案1】:

    为什么要这么复杂?为什么不简单

    map[itSecond->first] = itSecond->second;
    

    如果它们的键存在,则数据将被更改。如果密钥不存在,则将插入该对。


    也不要忘记std::map(以及std::unordered_map)的value_type是std::pair&lt;const Key, T&gt;。

    由于键是常量,您不能简单地分配或复制迭代器,您只能分配或复制值。

    【讨论】:

    • 谢谢!我仍然将代码保持原样,但出于某种原因,我想到 operator[] 不会更改值,但是通过查看返回 T& 的声明可以清楚地看到它。是的,value_type 是 std::pair ,因为我自己已经弄清楚了,所以无法更改密钥。
    【解决方案2】:

    回答第一个问题

    std::map 中迭代器的赋值应该如何表现?

    :

    MapT::Iterator满足BidirectionalIterator,满足ForwardIterator,满足Iterator。

    Iterator 是 CopyAssignable。

    所以分配t = v; 将完成

    • t 的值等价于v 的值。
    • v 的值不变。

    在这种情况下,将t 替换为pair.first,将v 替换为itSecond。请注意,地图不会因此而改变。

    (想象一下指针。当然分配指针不会修改它们指向的内容)

    【讨论】:

    • (元注释:非常简单。不要过度复杂化。)
    • (第二个问题见this another answer。应该已经够好了,我不需要重复了)
    【解决方案3】:

    假设C++17没问题,可以使用merge:https://en.cppreference.com/w/cpp/container/map/merge

    但它不会覆盖数据,因此您必须将第一个数据合并到第二个数据中。

    【讨论】:

      猜你喜欢
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 2021-06-15
      • 2012-07-18
      • 2019-05-11
      • 1970-01-01
      相关资源
      最近更新 更多