将大量数据初始化为C ++容器的最佳方法是什么?

时间:2014-04-01 20:26:54

标签: c++ containers constants hardcode large-data

例如:

InitEmployee()
{
    vector<Employee> employeeList = {
        Employee("Clark Kent",0),
        Employee("Bruce Wayne",1),
        ...
        Employee("Hal Jordan",65535)
    }
}

我无法从文件或数据库进行查询,因为此程序需要位于单个可执行文件中,因此所有常量数据都必须进行硬编码。我实际上使用boost的multi_index_container按名称和id进行快速查找但是为了简单起见,我在这里使用了vector作为示例。问题是我在单个函数中没有那么多(2 ^ 16)个常量数据而没有堆栈溢出。有没有更好的方法来初始化这个列表而不拆分函数?

我正在使用VC12。谢谢!

更新

参见所选答案。正如其他人所提到的,使用static会强制它继续数据而不是堆栈。这就是我最终的结果:

InitEmployee()
{
    static Employee employeeList[] = {
        {"Clark Kent",0},
        {"Bruce Wayne",1},
        ...
        {"Hal Jordan",65535}
    }

    vector<Employee*> employeeVec;
    int count = sizeof(employeeList) / sizeof(Employee);
    for (int i = 0; i < count; i++)
    {
        employeeVec.emplace(&employeeList[i]);
    }
}

事情是Employee类使用的是字符串类而不是c-string,所以我不想在内存中使用它的两个副本。这样我最终只得到指针的额外内存,这仍然是很多,但我相信这是最好的选择!也适用于multi_index_container!感谢

4 个答案:

答案 0 :(得分:5)

使用静态数组存储初始化数据。

InitEmployee()
{
    static char const* const names[] = {
        "Clark Kent",
        "Bruce Wayne",
        ...
        "Hal Jordan"
    };

    size_t const n = sizeof(names) / sizeof(*names);

    vector<Employee> employeeList;
    employeeList.reserve(n);
    for (size_t i=0; i<n; ++i)
        employeeList.emplace_back(names[i],i);
    ...
}

答案 1 :(得分:0)

你确定太多的字符串文字会导致堆栈溢出吗? 即使他们愿意,你也可以尝试将它们放在全球范围内:

const char *data = R"(
Clark Kent,0
Bruce Wayne,1
...
Hal Jordan,65535)"

/* ... */

int main()
{
    /* ... */
}

如果用大字符串文字编译好,你甚至可以尝试使用某些DB文件中的原始数据而不是列表。

答案 2 :(得分:0)

由于您说您正在使用VC 12,并且您有一个可执行文件(并且没有数据文件),因此将硬编码数据放在资源中,而不是程序代码中。

适合的资源是RCDATA类型。 http://msdn.microsoft.com/en-us/library/windows/desktop/aa381039(v=vs.85).aspx

答案 3 :(得分:0)

有两种选择可供选择。第一个取决于Visual Studio的版本。您使用的是Visual Studio 2012还是版本12.0(令人困惑的是,VS2012实际上是11.0)。如果您使用2013(即12.0),那么您可以选择使用C ++ 11中新增的初始化列表(例如,参见FAQ

vector<Employee> employeeList = {
    {"Clark Kent",0},
    {"Bruce Wayne",1},
    ...
    {"Hal Jordan",65535}
};

初始化列表依赖于C ++ 11 rvalue移动语义,以确保您最终只得到应用程序中的一个数据副本。

另一种选择可能是使用boost::assign(请参阅docs),这意味着您可以使用相同类型的语法,但动态进行分配:

#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace boost::assign; // bring operator+= into scope
vector<Employee> employeeList;
employeeList += Employee("Clark Kent", 0),
                Employee("Bruce Wayne", 1), ...