如何处理带有底层排序向量的映射中的const值

How to handle const values in a map with an underlying sorted vector?

本文关键字:向量 排序 映射 const 何处理 处理      更新时间:2023-10-16

我正在创建一个映射,它的底层实现作为一个排序的向量。它很可能最终与Boost的平面地图非常相似。其思想是通过将映射中的所有对存储在连续内存中,从而牺牲较慢的插入和删除速度以获得更快的访问速度。它也被设计成地图的替代品,具有完全相同的界面。迭代器失效会有一些不同于map契约的问题,但我准备处理这些问题。我所面临的问题的一个简单的解释是这段(非编译)代码:

#include <iostream>
#include <vector>
#include <algorithm> 
using namespace std;
int main()
{
    const int a = 10;
    int b = 20;
    pair<const int, int> constPair1(a,b);
    b=30;
    const int c = 40;
    pair<const int, int> constPair2(c,b);
    vector<pair<const int, int>> vec{constPair1,constPair2};
    sort(vec.begin(),vec.end());
    return 0;
}

我遇到的问题是如何处理const。上面的代码将无法编译,因为sort不允许在const对周围移动。Boost平面地图似乎只是忽略了这个问题,并放弃了const限定符,然而,我想要一个替换的下降,所以这不是一个选择。如何维护相同的接口,但仍然允许底层排序接口?如果可能的话,我想避免const_cast

问题是const语义非常粗糙,例如使用const对象的非const数组或非const对象的const数组就不适合这种模式。

一种可能的解决方法是将数据保存在非const数组中,并使用指针强制转换技巧来提供接口。换句话说,当您通过pair<const int, int> p时,只需使用pair<int, int>& ncp(*((pair<int, int>*)&p));即可。当向用户返回对象时,也可以这样做。

正式IIRC不能保证工作,但在实现中我知道是ok的,优化器应该足够聪明,不会为这种观点的改变生成代码。一个问题可能是严格的混叠假设优化(顺便说一句,这给很多底层代码带来了问题),在这种情况下,可能使用联合可以解决这个问题(当然仍然不符合标准)。

编辑

实际上,在我看来,这样的"映射"会有更多的问题,而不仅仅是迭代器无效。例如,我使用的模式(我打赌其他人也使用)依赖于迭代器可能无效的事实,但值本身永远不会移动……例如,在执行

之后
MyClass& foo() {
   ...
   return my_map[key];
}

我可以肯定,即使从映射中添加或删除了其他元素,返回的引用仍然有效。注意这里没有使用迭代器。

将元素保存在vector容器中,并在插入元素时移动它们(或者在插入后第一次访问时移动它们)也会破坏这种用法。