编译时数据结构的数量结构?

时间:2013-03-19 02:24:15

标签: c++ c++11 compile-time

在C ++中,你可以这样做:

static const char * [4] = {
   "One fish",
   "Two fish",
   "Red fish",
   "Blue fish"
};

...这为您提供了一个很好的只读数组数据结构,它不需要在运行时初始化任何CPU周期,因为所有数据都已经为您布局(在可执行文件的只读内存中)页面)由编译器。

但是,如果我宁愿使用不同的数据结构而不是数组呢?例如,如果我希望我的数据结构通过密钥快速查找,我必须做这样的事情:

static std::map<int, const char *> map;

int main(int, char **)
{
   map.insert(555, "One fish");
   map.insert(666, "Two fish");
   map.insert(451, "Red fish");
   map.insert(626, "Blue fish");

   [... rest of program here...]
}

...当地图数据结构在运行时被填充时,它不那么优雅且效率较低,即使所有必要的数据在编译时都是已知的,因此该工作可以(理论上)完成。

我的问题是,在C ++(或C ++ 11)中是否有任何方法可以创建只读数据结构(例如地图),其数据在编译时完全设置并因此预先填充并准备好在运行时使用数组的方式?

4 个答案:

答案 0 :(得分:8)

如果您想要地图(或集),请考虑使用binary tree stored as an array。您可以断言它在调试版本中在运行时正确排序,但在优化版本中,您可以假设所有内容都已正确排列,然后可以执行与std :: map中相同的二进制搜索操作,但使用底层存储是一个数组。在将数据粘贴到程序之前,只需编写一个小程序来为您堆积数据。

答案 1 :(得分:4)

不容易,不。如果您尝试使用malloc执行第一个示例,显然它在编译时不起作用。由于每个标准容器都使用new(好,std::allocator<T>::allocate(),但我们现在假装它是new,我们不能在编译时这样做。

有人说,这取决于你愿意经历多少痛苦,以及你想要多少回到编译时间。你当然不能只使用标准库功能。另一方面使用boost::mpl ......

#include <iostream>

#include "boost/mpl/map.hpp"
#include "boost/mpl/for_each.hpp"
#include "boost/mpl/string.hpp"
#include "boost/mpl/front.hpp"
#include "boost/mpl/has_key.hpp"

using namespace boost::mpl;

int main()
{
    typedef string<'One ', 'fish'> strone;
    typedef string<'Two ', 'fish'> strtwo;
    typedef string<'Red ', 'fish'> strthree;
    typedef string<'Blue', 'fish'> strfour;

    typedef map<pair<int_<555>, strone>,
        pair<int_<666>, strtwo>,
        pair<int_<451>, strthree>,
        pair<int_<626>, strfour>> m;

    std::cout << c_str<second<front<m>::type>::type>::value << "\n";
    std::cout << has_key<m, int_<666>>::type::value << "\n";
    std::cout << has_key<m, int_<111>>::type::value << "\n";
}

答案 2 :(得分:2)

值得一提的是,您的问题源于您使用地图的事实。 地图经常被滥用。 映射的替代解决方案是已排序的向量/数组。当数据用于存储未知长度的数据时,或者(有时仅在数据频繁更改时),地图仅比地图“更好”。

函数std :: sort,std :: lower_bound / std :: upper_bound是你需要的。 如果您可以自己对数据进行排序,则只需要一个函数lower_bound,数据可以是const。

答案 3 :(得分:0)

是的,C ++ 11允许使用大括号初始值设定项:

std::map<int, const char *> map = {
  { 555, "One fish" },
  { 666, "Two fish" },
  // etc
};