Orl*_*iev 0 c# c++ dictionary hashtable map
我一直觉得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)复杂度 - 无所谓.无论如何,每天的词典只有几个条目.易用性至关重要.
语法通常应该类似于数组.这意味着一个多功能的操作员[],如:
字典[key] =价值; //插入和更新字典[key] = NULL; //删除元素if(dictionary [key])//检查元素是否存在.不应插入默认构造的值!
Java和Objective-C没有运算符重载,所以这是不可能的.C#拥有它并充分利用它.C++不能这样做吗?
值和键都可以是自定义的用户定义类型或基本类型(整数,浮点数等).
存储用户定义的对象时,它们应该由shared_ptr引用.我正在使用Boost,所以这对于防止内存泄漏至关重要.其他三个平台要么是垃圾收集(C#/ Java),要么可以选择手动内存管理,引用计数和垃圾收集(目标C).Boost在实现引用计数方面做得很好,所以它应该是可能的.这正是Objective-C的NSDictionary在ARC开启的基础上制作的.
存储用户定义的对象时,默认情况下应根据内存地址对它们进行比较.非常重要:用户定义的对象不需要哈希函数,operator ==,operator <,公共基类等.需要这些东西可以明确地将比较从内存地址更改为其他内容,例如字符串的按值比较.但大多数时候我们只想要内存地址比较.
存储原始数据类型时,应按值进行比较.它们是否在某个内部对象中被包装/装箱应该与用户无关.再次,性能无关紧要.
使用if(dictionary [key])检查是否存在给定键的值.这不应该像在Boost和STL中那样插入默认的构造值对象.
应该为键和值强类型化.所以没有空虚*.此外,键和值都不需要公共基类,因为这会过于干扰并且会使第三方类更难以存储在地图中.
独特的钥匙.不允许空值(空值导致删除).
密钥应该可以作为向量或数组访问,并且可以通过索引进行遍历.迭代器需要太多输入.也就是说,我们应该能够写:
for(int i = 0; i <dictionary.getKeys().getCount(); i ++){shared_ptr value = dictionary [dictionary.getKeys()[i]]; }
必须编写充满迭代器声明的庞大for循环,这会使源代码的清晰度变得混乱.迭代器的typedef也不好,因为它们只会因为你遇到的每一个新的"Go To Definition"而增加复杂性,特别是在阅读别人的代码时.
我想我可以在列表中添加更多点数,但我会停在这里.您是否知道任何图书馆的地图类至少满足其中的大部分要点?我非常感谢任何建设性的反馈.
utn*_*tim 10
我将逐一解决你的观点.在许多方面,你所要求的对C++来说是不现实的(就像在Java中询问支持自定义运算符的地图一样是不现实的).
以下是关于Boost和STL实现的主要痛点以及我想要的内容:
首先,表现不是问题.内存分配,虚函数调用,O(n)复杂度 - 无所谓.无论如何,每天的词典只有几个条目.易用性至关重要.
在问题出现之前,性能始终"不是问题",当它出现问题时,它可以使您的项目陷入困境.这就是为什么通常,当性能不是问题时,仍然记住它是好的.没有自尊的库会暴露具有API规范的概念实现(例如地图/字典),例如"性能不是问题".如果有一个(虽然我认为不应该),它将以有效的方式实现,或者在库中你应该远离它.
2.语法通常应该类似于数组.这意味着一个多功能的操作员[],如:
字典[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;
Run Code Online (Sandbox Code Playgroud)
最后一行是将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;
Run Code Online (Sandbox Code Playgroud)
哪个novalue
是特殊常数,概念上代表"无".
if(dictionary [key])//检查元素是否存在.
再次,在通用映射中用C++实现这不是一个好主意.考虑这张地图:
IdealMap<int, bool> bool_map;
bool_map[0] = true;
if(bool_map[0]) {...}
Run Code Online (Sandbox Code Playgroud)
你在这里检查一个元素是否存在于零位置,或者该元素是否为真?
不应插入默认构造的值!
通过将地图封装在自定义类中来实现自己是微不足道的.
其余的点听起来更像购物清单.对不起,没有人写过匹配它的字典类(也就是说,没有,没有像你想要的那样编写字典的库).
必须编写充满迭代器声明的庞大for循环,这会使源代码的清晰度变得混乱.迭代器的typedef也不好,因为它们只会因为你遇到的每一个新的"Go To Definition"而增加复杂性,特别是在阅读别人的代码时.
for循环庞大的写作是不是你的东西永远要做.如果你有,你的问题是你的代码库(恕我直言)缺乏重构,而不是地图.
归档时间: |
|
查看次数: |
2874 次 |
最近记录: |