大型地图的静态初始化

时间:2016-12-28 01:20:08

标签: c++ static-initialization

我正静态初始化一个大的(~20kb)std :: unordered_map

const std::unordered_map<std::string, std::string> mapStringToString{
{"AAF", "ELN"}, {"ACT", "POC"}, {"AEK", "THJ"}, {"AFO", "EUP"},
{"AHB", "HYW"}, {"AIB", "GFW"}, {"AJX", "BUX"}, {"ALD", "FKP"},
{"ALX", "LWB"}, {"AMY", "NQB"}, {"AOI", "GUC"}, {"ASW", "VMH"},
{"ATQ", "SXK"}, {"AVL", "ENB"}, {"BCJ", "NSX"}, {"BEM", "QVR"},
{"BGU", "WPU"}, {"BJR", "ZCS"}, {"BJT", "ZTK"}, {"BOY", "FYU"},
...
{"XSJ", "FRR"}, {"XUD", "NUI"}, {"XVH", "QTI"}, {"XVJ", "TGG"},
{"XWK", "AZB"}, {"XYQ", "YTO"}, {"YAG", "ZQR"}, {"YAY", "UJY"},
{"YBN", "FEB"}, {"YCR", "EPQ"}, {"YHU", "UUD"}, {"YIG", "YMJ"},
{"YME", "EEZ"}, {"YNE", "EIU"}, {"YTC", "IOC"}, {"YTS", "JQM"},
{"YUH", "JPF"}, {"ZDY", "LFQ"}, {"ZFY", "YIH"}, {"ZMF", "BPK"},
{"ZPR", "TNG"}, {"ZTM", "DFJ"}, {"ZVB", "ZSV"}, {"ZXH", "IOA"},
{"ZZR", "RQG"}};

并且代码分析抱怨堆栈使用:

C6262   Excessive stack usage   Function uses '19920' bytes of stack:  exceeds /analyze:stacksize '16384'.. This allocation was for a compiler-generated temporary for 'struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > [249]' at line 0.  Consider moving some data to heap.     <no file>   

如果表中的所有数据都作为unordered_map构造函数的一部分放在堆栈中,则此警告是合理的。

有更好的方法进行初始化吗?

1 个答案:

答案 0 :(得分:2)

任何合理大小的地图最好从文件初始化:除了避免堆栈大小的问题,它也往往更容易维护。另一方面,有可能由于某种原因无法访问该文件,并且将数据嵌入到程序中可能是有利的,特别是当它基本上不可变时。注意,生成的映射的const没有问题:映射可以由迭代器序列构造,该迭代器可以从文件中读取。以下是此方法的示例:

#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>

struct mystring
    : std::string {
};

std::istream&
operator>> (std::istream& in, std::pair<mystring, std::string>& p) {
    in >> p.first >> p.second;
    return in;
}

using pair     = std::pair<mystring, std::string>;
using iterator = std::istream_iterator<pair>;
using map_type = std::unordered_map<std::string, std::string>;
map_type const map(iterator(std::ifstream("map.txt") >> std::skipws), iterator());

int main()
{
    for (auto const& p: map) {
        std::cout << "'" << p.first << "'->'" << p.second << "'\n";
    }
}

类型mystring需要具有输入操作符可以重载的类型:仅使用标准库类型,标准库定义输入操作符是必要的但它不会如此。

由于我们显然可以使用迭代器指定的序列而不是std::initializer_list<...>,因此在程序中存储数据的替代方法是使用相应元素的静态数组,然后将其用作初始化映射的基础序列。例如:

#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>

std::pair<std::string const, std::string> values[] = {
    { "foo1", "bar1" },
    { "foo2", "bar2" },
    { "foo3", "bar3" },
    { "foo4", "bar4" }
};
using map_type = std::unordered_map<std::string, std::string>;
map_type const map(std::begin(values), std::end(values));

int main()
{
    for (auto const& p: map) {
        std::cout << "'" << p.first << "'->'" << p.second << "'\n";
    }
}
相关问题