初始化静态 std::map在 C++
初始化静态地图的正确方法是什么? 我们需要一个静态函数来初始化它吗?
What is the right way of initializing a static map? Do we need a static function that will initialize it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
这是使用 2 元素数据构造函数的另一种方法。 不需要任何函数来初始化它。 没有第 3 方代码(Boost),没有静态函数或对象,没有技巧,只有简单的 C++:
自从我写了这个答案以来,C++11 已经出来了。 您现在可以使用新的初始化程序列表功能直接初始化 STL 容器:
Here is another way that uses the 2-element data constructor. No functions are needed to initialize it. There is no 3rd party code (Boost), no static functions or objects, no tricks, just simple C++:
Since I wrote this answer C++11 is out. You can now directly initialize STL containers using the new initializer list feature:
例如:
如果map是类的数据成员,则可以通过以下方式直接在头文件中初始化它(C++17起):
For example:
If map is a data member of a class, you can initialize it directly in header by the following way (since C++17):
我会将地图包装在静态对象内,并将地图初始化代码放入该对象的构造函数中,这样您就可以确保在执行初始化代码之前创建地图。
I would wrap the map inside a static object, and put the map initialisation code in the constructor of this object, this way you are sure the map is created before the initialisation code is executed.
只是想分享一个纯 C++ 98 的解决方法:
Just wanted to share a pure C++ 98 work around:
使用 C++11 初始值设定项列表 {{},{},...}。 初始化元素的顺序并不重要。 地图将根据按键为您进行排序。 如果初始化 unordered_map,则原理相同,排序顺序将由哈希函数确定,并且在人眼看来是随机的:
使用 Boost.Assign:
Using C++11 initializer list {{},{},...}. The order of the initialized elements does not matter. The map will do the ordering by the key for you. If initializing unordered_map, it is the same principle where the sorted order will be determined by the hashing function and will appear to human eye as random:
Using Boost.Assign:
最好的方法是使用一个函数:
Best way is to use a function:
制作类似boost的东西并不是一个复杂的问题。 这是一个只有三个函数(包括构造函数)的类,用于复制 boost 所做的(几乎)。
用法:
上面的代码最适合初始化全局变量或需要初始化的类的静态成员,您不知道它何时首先使用,但您想确保其中的值可用。
如果说,您必须将元素插入现有的 std::map...这是为您准备的另一个类。
用法:
在 GCC 4.7.2 中查看它的运行情况:http://ideone.com/3uYJiH
############### 下面的所有内容都已过时 #################
编辑:下面的
map_add_values
类(这是我建议的原始解决方案)在 GCC 4.5+ 中会失败。 请查看上面的代码,了解如何向现有地图添加值。用法:
注意:以前我使用
运算符[]
来添加实际值。 正如达勒评论的那样,这是不可能的。#################### 过时部分结束 #####################< /强>
It's not a complicated issue to make something similar to boost. Here's a class with just three functions, including the constructor, to replicate what boost did (almost).
Usage:
The above code works best for initialization of global variables or static members of a class which needs to be initialized and you have no idea when it gets used first but you want to assure that the values are available in it.
If say, you've got to insert elements into an existing std::map... here's another class for you.
Usage:
See it in action with GCC 4.7.2 here: http://ideone.com/3uYJiH
############### EVERYTHING BELOW THIS IS OBSOLETE #################
EDIT: The
map_add_values
class below, which was the original solution I had suggested, would fail when it comes to GCC 4.5+. Please look at the code above for how to add values to existing map.Usage:
NOTE: Previously I used a
operator []
for adding the actual values. This is not possible as commented by dalle.##################### END OF OBSOLETE SECTION #####################
你在这里有一些非常好的答案,但对我来说,这看起来像是“当你所知道的只是一把锤子时”的情况......
关于为什么没有标准方法来初始化静态地图的最简单的答案,没有充分的理由使用静态映射...
映射是一种为快速查找一组未知元素而设计的结构。 如果您事先知道元素,只需使用 C 数组即可。 以排序的方式输入值,或者对它们运行排序(如果您无法执行此操作)。 然后,您可以通过使用 stl::functions 循环条目 lower_bound/upper_bound 来获得 log(n) 性能。 当我之前对此进行测试时,它们的执行速度通常比地图快至少 4 倍。
优点有很多...
- 更快的性能(*4,我对许多 CPU 类型进行了测量,它总是在 4 左右)
- 更简单的调试。 使用线性布局更容易看到发生了什么。
- 复制操作的简单实现(如果有必要的话)。
- 它在运行时不分配内存,因此永远不会抛出异常。
- 它是一个标准接口,因此很容易在 DLL 或语言等之间共享。
我可以继续,但如果您想要更多,为什么不看看 Stroustrup 关于该主题的许多博客。
You have some very good answers here, but I'm to me, it looks like a case of "when all you know is a hammer"...
The simplest answer of to why there is no standard way to initialise a static map, is there is no good reason to ever use a static map...
A map is a structure designed for fast lookup, of an unknown set of elements. If you know the elements before hand, simply use a C-array. Enter the values in a sorted manner, or run sort on them, if you can't do this. You can then get log(n) performance by using the stl::functions to loop-up entries, lower_bound/upper_bound. When I have tested this previously they normally perform at least 4 times faster than a map.
The advantages are many fold...
- faster performance (*4, I've measured on many CPU's types, it's always around 4)
- simpler debugging. It's just easier to see what's going on with a linear layout.
- Trivial implementations of copy operations, should that become necessary.
- It allocates no memory at run time, so will never throw an exception.
- It's a standard interface, and so is very easy to share across, DLL's, or languages, etc.
I could go on, but if you want more, why not look at Stroustrup's many blogs on the subject.
除了使用的最佳答案之外,
还有一种直接调用 lambda 的可能性,这在某些情况下很有用:
显然,当使用文字值从头开始编写时,简单的初始值设定项列表更好,但它确实开辟了其他可能性:(
显然,如果您想重用它,它应该是一个普通函数;并且这确实需要最新的 C++。)
In addition to the good top answer of using
there's an additional possibility by directly calling a lambda that can be useful in a few cases:
Clearly a simple initializer list is better when writing this from scratch with literal values, but it does open up additional possibilities:
(Obviously it should be a normal function if you want to re-use it; and this does require recent C++.)
如果您坚持使用 C++98 并且不想使用 boost,这里有我在需要初始化静态映射时使用的解决方案:
If you are stuck with C++98 and don't want to use boost, here there is the solution I use when I need to initialize a static map:
这与
PierreBdR
类似,但无需复制地图。This is similar to
PierreBdR
, without copying the map.你可以试试:
You can try: