Closed. This question is
off-topic。它当前不接受答案。
想改善这个问题吗?
Update the question,所以它是
on-topic,用于堆栈溢出。
5年前关闭。
对于C ++编程,我经常发现不方便的一件事是它缺少良好的map / dictionary / hash table / associative array容器类。 C#,Java和Objective-C都有类似的类,即Dictionary <>,Hashtable和NSDictionary,它们几乎可以直接使用所有数据类型。但是STL的stl :: map和Boost的boost :: unordered_map都非常笨拙且过于冗长,即使是日常琐事也是如此。我想知道在某些开放源代码库中是否存在与上述平台的语法和功能更相似的C ++等效项。
在这三种语言中,C#的Dictionary <>是我的最爱,因为它是强类型的,语法非常简短,用途广泛。所以类似的东西将是完美的。我不确定这是否完全可能。如果没有,我想知道原因。这是我关于Boost和STL实施的主要痛点,以及我想要的:
首先,性能不是这里的问题。内存分配,虚拟函数调用,O(n)复杂性-无关紧要。无论如何,每天的词典只有几个条目。易于使用至关重要。
语法通常应类似于数组的语法。这意味着通用运算符[],例如:
dictionary [key] =值; //插入和更新
dictionary [key] = NULL; //删除一个元素
if(dictionary [key])//检查元素是否存在。不得插入默认构造的值!
Java和Objective-C没有运算符重载,因此它们是不可能的。 C#拥有并充分利用了它。 C ++不能一样吗?
值和键都可以是自定义的用户定义类型或原始类型(int,float等)。
存储用户定义的对象时,应使用shared_ptr引用它们。我正在使用Boost,因此这对于防止内存泄漏至关重要。其他三个平台要么是垃圾回收(C#/ Java),要么可以选择手动内存管理,引用计数和垃圾回收(目标C)。 Boost很好地实现了引用计数,因此应该可以实现。这就是在打开ARC的情况下Objective-C的NSDictionary所做的事情。
存储用户定义的对象时,默认情况下应根据内存地址对它们进行比较。非常重要:对于用户定义的对象,不需要哈希函数,operator ==,operator <,通用基类等。要求这些事情可以将比较从内存地址显式更改为其他内容,例如字符串的按值比较。但是大多数时候我们只想比较内存地址。
存储原始数据类型时,应按值对它们进行比较。它们是否包装/装在某些内部对象中与用户无关。再次,性能无关紧要。
使用if(dictionary [key])可以检查给定键是否存在值。不应像在Boost和STL中那样插入默认的构造值对象。
对于键和值均应为强类型。所以没有空*。同样,键和值都不需要通用的基类,因为这会太麻烦,并且会使第三方类更难存储在地图中。
唯一键。不允许使用空值(空值会导致删除)。
键应可作为向量或数组访问,并可以按索引遍历。迭代器需要太多的输入。也就是说,我们应该能够写:
for(int i = 0; i
shared_ptr值=字典[dictionary.getKeys()[i]];
}
必须编写充满迭代器声明的gargantuan for循环会混淆源代码的清晰度。而且,用于迭代器的typedef也不是一件好事,因为它们只会增加复杂性,因为您遇到的每一个新代码都必须“定义到”,特别是在阅读别人的代码时。
我想我可以在列表中添加更多点,但是我就在这里停止。您是否知道任何一个地图类至少满足大多数要求的图书馆?如有任何建设性的反馈,我将不胜感激。
我将一一阐述您的观点。在许多方面,您要问的对C ++都是不现实的(就像在Java中向支持自定义运算符的地图提问一样)。
这是我关于Boost和STL实施的主要痛点,以及我想要的:
1.首先,性能不是这里的问题。内存分配,虚拟函数调用,O(n)复杂性-无关紧要。无论如何,每天的词典只有几个条目。易于使用至关重要。
在出现问题之前,性能始终是“不是问题”,并且在出现问题时,性能可能会下降。这就是为什么通常情况下,当性能不是问题时,最好记住这一点。没有一个自重的库会公开带有API规范(例如“性能不是问题”)的概念实现(例如地图/字典)。如果有一个(尽管我认为应该没有),它将以一种有效的方式实现,或者在一个库中,您可能应该远离它。
2.语法通常应类似于数组的语法。这意味着通用运算符[],例如:
dictionary [key] =值; //插入和更新
这已经实现了C ++ std :: map
dictionary [key] = NULL; //删除一个元素
对于C ++,这是不现实的。通过自定义引用包装器访问值并使用nullptr使该值可分配,可以实现它。问题是在C ++中,指针是另一种数据类型。
也就是说,这意味着什么?
IdealMap<int, my_obj*> pointer_map;
pointer_map[1] = new my_obj{};
pointer_map[1] = nullptr;
最后一行是将poiter_map [i]设置为NULL,还是确保从这一点开始对元素i的任何访问都将引发“未找到”异常?
您可以交替编写这样的实现:
IdealMap<int, my_obj*> pointer_map;
pointer_map[1] = new my_obj{};
pointer_map[1] = IdealMap<int, my_obj*>::novalue;
其中
novalue
是一个特殊常数,概念上表示“无”。
if(dictionary [key])//检查元素是否存在。
同样,在通用映射中用C ++实现不是一个好主意。考虑这张地图:
IdealMap<int, bool> bool_map;
bool_map[0] = true;
if(bool_map[0]) {...}
您是否在此处检查元素是否存在于零位置,或者该元素为真?
不得插入默认构造的值!
通过将地图封装在自定义类中,实现自己很简单。
您剩下的要点听起来更像是购物清单。抱歉,没有人编写与之匹配的字典类(也就是说,没有库完全按照您的意愿编写字典)。
必须编写充满迭代器声明的gargantuan for循环会混淆源代码的清晰度。而且,用于迭代器的typedef也不是一件好事,因为它们只会增加复杂性,因为您遇到的每一个新代码都必须“定义到”,特别是在阅读别人的代码时。
无需编写庞大的for循环。如果您有这个问题,那么您的问题就是缺乏代码库(IMHO)中的重构,而不是映射。