【问题标题】:std::map change key_comp after initializationstd::map 初始化后更改 key_comp
【发布时间】:2012-12-05 19:02:17
【问题描述】:

std::map 创建和初始化后是否可以更改比较方法? 或者也许只有在它被创建之后??

我想以某种方式更改包含我无法更改定义的映射的类的行为。我想通过传递另一张地图来改变它的比较行为。

【问题讨论】:

  • 您是否在此处看到允许您直接执行此操作的功能:en.cppreference.com/w/cpp/container/map?如果不是,那么答案是否定的……
  • 它是一个模板参数,所以它必须在编译时修复。改变它会改变容器的类型。

标签: c++ stl stdmap


【解决方案1】:

这是不可能的。但是您可以创建一个新地图,使用替代比较标准和两个迭代器构造函数来使用第一个中的元素实例化地图。

bool  C1(const K&, const K&);
bool  C2(const K&, const K&);

std::map<K, V, C1> orig;
....
std::map<K, V, C2> alternative(orig.begin(), orig.end());

【讨论】:

    【解决方案2】:

    不,这是不可能的。比较器是地图的 type 的一部分。这个问题与询问您是否可以更改int 来存储浮点数没有什么不同。

    更重要的是,比较器提供的排序是地图内部结构的一个组成部分。如果您要更改排序,则数据结构将不再处于一致状态。唯一可行的选择是根据新顺序从旧地图的元素重建新地图,但这已经是可能的:

    std::map<T, V, Comp1> m1 = /* ... */;
    std::map<T, V, Comp2> m2(m1.begin(), m1.end());
    

    或者,您可以制作第二张std::map&lt;std::reference_wrapper&lt;T const&gt;, std::reference_wrapper&lt;V&gt;, Comp2&gt; 类型的地图并使用对原始地图的引用填充它,但根据Comp2 排序。在这种情况下,您有责任保持两个地图同步。像 Boost.Multiindex 这样的高级容器可以安全地为您执行此操作。

    【讨论】:

      【解决方案3】:

      也许有可能,这是未经测试的:

      1. 定义您自己的自定义比较器,它内部有一个指向比较函数实际实现的指针
      2. 将 this 的一个实例传递给地图的构造函数(您也必须使用此比较器键入地图。)
      3. 稍后设置真正的实现(在使用地图之前),如果设置之后,你不知道对内部的影响......

      已经测试过了,上面是可以做到的,但是如果树中有项目,改变比较函数可能是灾难性的......

      无论如何 - 这听起来太可疑了......

      【讨论】:

      • 没关系。地图是空的。
      • @djWann 我认为每次通过函数指针调用 compare 的开销会显着减慢 map 操作,如果你关心的话。
      • @djWann 如果地图是空的,为什么不使用一个新的呢?两个完全不同的对象,或者只要比较器的签名相同:my_map = std::map&lt;...&gt;(&amp;new_compare);
      【解决方案4】:

      不,这是不可能的,因为它是通过模板参数编译到地图中的。

      请参阅:http://www.cplusplus.com/reference/map/map/ 比较是您要查找的内容。

      你想做什么?

      由于您将类作为 Key 使用,因此您可以实现 constructor,因此应该可以传递所有内容以实现依赖于上下文的同情。问题是,你为什么要这样做?

      在运行时更改 std::map 的比较是一个坏主意,因为它会导致未定义的行为。仅仅基于 std::map 的内容是“排序的”(可能是 RB-tree)这一事实。如果你改变排序函数,你会突然改变逻辑顺序;但地图不会神奇地重新排序。下一次调用 insert 或 find 可能不会如您所愿。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        相关资源
        最近更新 更多