使用不同的键搜索数据 我不是C++和STL的专家。
我使用地图中的结构作为数据。钥匙是C1类的。 我希望访问相同的数据,但也使用不同的键C2(其中C1和C2是两个不相关的类) 这在不复制数据的情况下是可能的吗? 我试着在谷歌上搜索,但很难找到一个我能理解的答案 这适用于不支持boost库的嵌入式目标使用不同的键搜索数据 我不是C++和STL的专家。,c++,stl,C++,Stl,我使用地图中的结构作为数据。钥匙是C1类的。 我希望访问相同的数据,但也使用不同的键C2(其中C1和C2是两个不相关的类) 这在不复制数据的情况下是可能的吗? 我试着在谷歌上搜索,但很难找到一个我能理解的答案 这适用于不支持boost库的嵌入式目标 有人能提供帮助吗?不在标准库中,但Boost提供了两个不同类型的键 我必须承认我读错了一点,并没有真正注意到您需要两个不同类型的键,而不是值。不过,解决方案将基于以下内容。其他答案有很多需要的,我只想补充一点,您可以创建一个通用的查找函数:(C++1
有人能提供帮助吗?不在标准库中,但Boost提供了两个不同类型的键 我必须承认我读错了一点,并没有真正注意到您需要两个不同类型的键,而不是值。不过,解决方案将基于以下内容。其他答案有很多需要的,我只想补充一点,您可以创建一个通用的查找函数:(C++14 ish伪代码) 通过
数据[键[“多键”]]
访问
这显然会浪费一些空间(复制Key
类型的对象),但我假设它们比Data
类型小得多
想法2
另一个解决方案是使用指针;那么复制的唯一代价就是(智能)指针:
地图数据;
只要至少有一个键指向
数据的对象,该对象将处于活动状态。在这些情况下,我通常使用非自有指针。我将数据存储在向量中:
std::vector<Data> myData;
std::vector myData;
然后我将指针映射到每个元素。由于指针可能会因为向量的未来增长而失效,所以在本例中,我将选择使用向量索引
std::map<Key1, int> myMap1;
std::map<Key2, int> myMap2;
std::map myMap1;
std::map myMap2;
不要向客户端公开数据容器。将元素的插入和删除封装在特定函数中,这些函数到处插入,到处删除。Bartek的“想法1”很好(尽管没有令人信服的理由更喜欢无序映射
而不是映射
)
或者,您可以使用std::map
或std::map
在一次C2
键搜索后直接访问数据
对象,但是您需要更加小心,不要访问无效(已擦除的)数据
(或者更准确地说,从任何其他用户的角度,以原子方式从两个容器中擦除)
一个或两个map
s也可以移动到shared\u ptr
——另一个可以使用weak\u ptr
,如果这对所有权有帮助的话。(这些都在C++11标准中,否则明显的源代码boost显然不适合您,但可能您已经实现了自己的库或选择了另一个库?这是现代C++非常基本的类)
编辑-哈希表与平衡二叉树
这与问题并不特别相关,但已收到以下评论/兴趣,我需要更多的空间来适当解决。以下几点:
1) Bartek漫不经心地建议从map
更改为unordered_map
,而不建议进行影响研究,重新迭代/指针无效是危险的,而且没有理由认为需要(问题没有提到性能)也没有推荐进行分析
3) 程序中相对较少的数据结构对性能关键行为很重要,而且很多时候,一个与另一个的相对性能无关紧要。支持这一说法-大量代码是用std::map
编写的,以确保C++11之前的可移植性,并且执行得很好
P> 4)当表现是一个严重的问题时,建议应该是“Cale=“Profile”,但是说一条经验法则是可以的——与“不要过早悲观”(参见萨特和Alexandrescu的C++编码标准)一致。-如果这里有人问我,我很乐意推荐默认情况下的unordered\u map
-但这并不特别可靠。这与推荐我看到的每一种std::map
用法相去甚远
5) 这个容器性能方面的研究已经开始引入有用见解的特别片段,但还远远不够全面或平衡。这个问题不是进行这种讨论的合理场所。如果有另一个问题可以解决这个问题,继续讨论是有意义的,并且有人让我插手,我将在下一两个月的某个时候做。您可以将指向数据的指针存储为std::map
值,并且您可以有两个具有指向相同数据的不同键的映射
我认为在这种共享数据所有权的情况下,像std::shared\u ptr这样的智能指针是一个很好的选择:
#include <map> // for std::map
#include <memory> // for std::shared_ptr
....
std::map<C1, std::shared_ptr<Data>> map1;
std::map<C2, std::shared_ptr<Data>> map2;
#包含//用于std::map
#包含//用于std::shared\u ptr
....
地图地图1;
地图地图2;
<> > <代码>数据< /代码>可以使用<代码> STD::MaMaSyfSyd()/<代码> .< /P> < P>可以考虑有一个简单的<代码> STD::列表< /COD>保存所有的数据,然后各种<代码> STD::MAP< /COD>对象映射任意关键字值到指向列表的迭代器:
std::list<Data> values;
std::map<C1, std::list<Data>::iterator> byC1;
std::map<C2, std::list<Data>::iterator> byC2;
std::列出值;
std::map byC1;
std::map byC2;
也就是说,使用普通迭代器,而不是处理或多或少的原始指针。进入std::list
的迭代器有很好的失效保证。我也有同样的问题,起初为共享指针持有两个map听起来很酷。但您仍然需要管理这两个映射(插入、删除等)
然后我想出了另一种方法。
我的理由是;使用x-y或半径角度访问数据。想象一下,每个点都将保存数据,但点可以用笛卡尔x、y或半径角来描述
所以我写了一个类似
struct MyPoint
{
std::pair<int, int> cartesianPoint;
std::pair<int, int> radianPoint;
bool operator== (const MyPoint& rhs)
{
if (cartesianPoint == rhs.cartesianPoint || radianPoint == rhs.radianPoint)
return true;
return false;
}
}
struct MyPoint
{
std::成对笛卡尔点;
std::map<Key1, int> myMap1;
std::map<Key2, int> myMap2;
#include <map> // for std::map
#include <memory> // for std::shared_ptr
....
std::map<C1, std::shared_ptr<Data>> map1;
std::map<C2, std::shared_ptr<Data>> map2;
std::list<Data> values;
std::map<C1, std::list<Data>::iterator> byC1;
std::map<C2, std::list<Data>::iterator> byC2;
struct MyPoint
{
std::pair<int, int> cartesianPoint;
std::pair<int, int> radianPoint;
bool operator== (const MyPoint& rhs)
{
if (cartesianPoint == rhs.cartesianPoint || radianPoint == rhs.radianPoint)
return true;
return false;
}
}
std::unordered_map<MyPoint, DataType> myMultIndexMap;