2016-12-28 44 views
0

私は静的に大きな(〜20キロバイト)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

文字列をharcodingする代わりに、テキストファイル、つまり 'csv'から読み込むのはなぜですか? –

+0

このようなものhttp://stackoverflow.com/questions/10951447/load-stdmap-from-text-fileは間違いなく実行可能ですが、他の選択肢はありますか?可能であれば、マップ 'const'を維持したいと思います。 – jnnnnn

+0

tbh私はそこには良い方法があるとは思わない。テキストファイルから文字列を読み込むと、多くの利点があります。 1つは、キーの値が変わるたびに再コンパイルする必要はありません。また、csvをExcelで視覚化し、重複やエラーをチェックすることもできます。 –

答えて

2

妥当なサイズのマップは、ファイルから最もよく初期化されます。スタックサイズの問題を回避するだけでなく、保守が容易になる傾向があります。一方、ファイルが何らかの理由でアクセス可能でない可能性があり、データを埋め込むことは、特に本質的に不変である場合には、プログラムにとって好ましいことがある。結果として得られるマップの問題はないことに注意してください。ファイルから読み込むことができるイテレータのシーケンスによってマップを構築できます。ここでは、このアプローチの例は、次のとおり

#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<...>ではなくiteratorで指定されたシーケンスを使用することができるので、プログラム内のデータを格納する代替要素は、マップを初期化する基本シーケンスとして使用される対応する要素を持つ静的配列です。例:

#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"; 
    } 
} 
関連する問題