C++ 将std::map数据复制到另一个map

C++ 将std::map数据复制到另一个map,c++,dictionary,stl,C++,Dictionary,Stl,我有一张这样定义的地图 struct A { int A; int B; }; typedef map<int,A> Amap; 有时这可以正常工作,有时只复制键和值0。我的错误在哪里?可以使用operator=或copy构造函数将一个映射复制到另一个映射 例如 map-mp1; //用数据填充mp1 地图mp2(mp1)//mp2是mp1的副本(通过副本构造) 地图mp3; mp3=mp2;//mp3也是mp2的副本(通过副本分配) 假设Amap2为空,您上面发布

我有一张这样定义的地图

 struct A
 {
  int A;
  int B;
 };
 typedef map<int,A> Amap;

有时这可以正常工作,有时只复制键和值0。我的错误在哪里?

可以使用operator=或copy构造函数将一个映射复制到另一个映射

例如

map-mp1;
//用数据填充mp1
地图mp2(mp1)//mp2是mp1的副本(通过副本构造)
地图mp3;
mp3=mp2;//mp3也是mp2的副本(通过副本分配)

假设
Amap2
为空,您上面发布的代码将正常工作。如果尝试将键/值对插入到已保存该键的映射,则旧值将被保留,新值将被丢弃。因此,如果你写信

Amap2.insert(Amap1.begin(), Amap1.end());
在某些情况下,您可能无法按预期复制所有内容,因为重复的密钥无法复制

设置<代码> AMAP2<代码>等于<代码> AMAP1,只考虑使用赋值运算符:

Amap2 = Amap1;
但是,这会盲目地丢弃
Amap2
的内容,因此在执行此操作时要小心

如果您想以完全覆盖现有键/值对的方式将
Amap2
中的所有键/值对添加到
Amap1
中,则可以使用以下逻辑执行此操作。这里的想法类似于mergesort背后的逻辑-我们将映射视为排序值的序列,然后将两者连续地混合在一起:

void MergeMaps(map<int, A>& lhs, const map<int, A>& rhs) {
    map<int, A>::iterator lhsItr = lhs.begin();
    map<int, A>::const_iterator rhsItr = rhs.begin();

    while (lhsItr != lhs.end() && rhsItr != rhs.end()) {
        /* If the rhs value is less than the lhs value, then insert it into the 
           lhs map and skip past it. */
        if (rhsItr->first < lhsItr->first) {
            lhs.insert(lhsItr, *rhsItr); // Use lhsItr as a hint.
            ++rhsItr;
        }
        /* Otherwise, if the values are equal, overwrite the lhs value and move both
           iterators forward. */
        else if (rhsItr->first == lhsItr->first) {
            lhsItr->second = rhsItr->second;
            ++lhsItr; ++rhsItr;
        }
        /* Otherwise the rhs value is bigger, so skip past the lhs value. */
        else
            ++lhsItr;

    }

    /* At this point we've exhausted one of the two ranges.  Add what's left of the
       rhs values to the lhs map, since we know there are no duplicates there. */
    lhs.insert(rhsItr, rhs.end());
}
将所有键/值对从
Amap2
复制到
Amap1


希望这有帮助

如果我想确保覆盖现有密钥,我可以选择两个选项:我可以使用std::copy,但不是
std::inserter
,而是使用
operator[]
编写一个自定义的。另一种2-liner方法是复制rhsItr,然后定期将lhsItr插入副本,然后交换。@CashCow:与自定义插入方法相比,我的方法的主要优点是括号在平均情况下运行O(lg n),而我发布的代码应该在线性时间内运行,假设insert实现得很好,这是因为附近有迭代器的暗示。@Wolf:答案中给出了这两种方法。这是一个合作编辑的社区,如果您想添加答案,请随意编辑。@Wolf:请不要实质性地修改其他人的答案,尤其是五年前写的那些已经被人们投票并被OP接受的答案。请随意写自己的答案,竞争性回答。@LightnessRacesinOrbit我要求它,OP明确地授予我:
请随意编辑它。
@Wolf:OP错了。除非答案是新的,否则我们不会对其进行实质性修改。这对先前的选民或问题作者来说是不公平的。你可以在meta上找到这个指南。谢谢:)@Wolf:这是一个有争议的问题。关于Meta的问题问了很多,我不相信大家对此有任何共识。我个人认为,如果有实质性的改变,作者应该发布一个全新的答案;使所有现有选票无效似乎是不诚实的,无论多么善意。毕竟,他们被要求对原始内容/建议进行同行评审。
Amap2 = Amap1;
void MergeMaps(map<int, A>& lhs, const map<int, A>& rhs) {
    map<int, A>::iterator lhsItr = lhs.begin();
    map<int, A>::const_iterator rhsItr = rhs.begin();

    while (lhsItr != lhs.end() && rhsItr != rhs.end()) {
        /* If the rhs value is less than the lhs value, then insert it into the 
           lhs map and skip past it. */
        if (rhsItr->first < lhsItr->first) {
            lhs.insert(lhsItr, *rhsItr); // Use lhsItr as a hint.
            ++rhsItr;
        }
        /* Otherwise, if the values are equal, overwrite the lhs value and move both
           iterators forward. */
        else if (rhsItr->first == lhsItr->first) {
            lhsItr->second = rhsItr->second;
            ++lhsItr; ++rhsItr;
        }
        /* Otherwise the rhs value is bigger, so skip past the lhs value. */
        else
            ++lhsItr;

    }

    /* At this point we've exhausted one of the two ranges.  Add what's left of the
       rhs values to the lhs map, since we know there are no duplicates there. */
    lhs.insert(rhsItr, rhs.end());
}
MergeMaps(Amap1, Amap2);