如何使用std ::字符串作为stxxl ::地图键(How to use std::string

2019-10-19 22:36发布

我试图使用的std :: string作为一个关键的stxxl ::地图插入是罚款少数串约10-100的。 但是,当试图插入大量关于这10万串,我得到段错误。

代码如下:

struct CompareGreaterString {
    bool operator () (const std::string& a, const std::string& b) const {
       return a > b;
    }
    static std::string max_value() {
       return "";
    } 
};

// template parameter <KeyType, DataType, CompareType, RawNodeSize, RawLeafSize, PDAllocStrategy (optional)>
typedef stxxl::map<std::string, unsigned int, CompareGreaterString, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> name_map;
name_map strMap((name_map::node_block_type::raw_size)*3, (name_map::leaf_block_type::raw_size)*3);
for (unsigned int i = 0; i < 1000000; i++) { /// Inserting 1 million strings
    std::stringstream strStream;
    strStream << (i);
    Console::println("Inserting: " + strStream.str());
    strMap[strStream.str()]=i;
}

在这里,我无法确定为什么我无法插入多个字符串的数量。 我正好收到分段错误而将“1377”。 加上我能够作为键添加任何整数数量。 我觉得字符串变量大小可能会导致这样的麻烦。

另外,我无法理解什么返回max_value的字符串。 我简单地返回一个空字符串。

Answer 1:

根据文档 :

CompareType还必须提供一个静态MAX_VALUE方法,它返回类型关键字类型的值,该值是比存储在地图任意键较大

因为空字符串恰好比较比其他任何字符串作为小,它打破了这个先决条件,因此可能会导致不确定的行为。

这里有一个max_value应该工作。 MAX_KEY_LEN仅仅是一个整数,其是大于或等于最长可能字串密钥的长度,该地图可以有。

struct CompareGreaterString {
    // ...
    static std::string max_value() {
        return std::string(MAX_KEY_LEN, std::numeric_limits<unsigned char>::max());
    }
};


Answer 2:

我终于找到了解决我的问题与蒂莫bingmann,user2079303和马丁·巴很大的帮助。 谢谢。

我愿与你分享。

首先stxxl只支持POD。 这意味着它只能存储固定大小的结构。 因此的std :: string不能是一个关键。 stxxl ::因为它们包含在物理内存本身的地图工作约100-1000字符串。 当更多的字符串插入它到磁盘上在内部引发了一些问题写。

因此,我们需要利用炭[]如下使用固定的字符串:

static const int MAX_KEY_LEN = 16;

class FixedString { 
public:
    char charStr[MAX_KEY_LEN];

    bool operator< (const FixedString& fixedString) const {
        return std::lexicographical_compare(charStr, charStr+MAX_KEY_LEN,
            fixedString.charStr, fixedString.charStr+MAX_KEY_LEN);
    }

    bool operator==(const FixedString& fixedString) const {
        return std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
    }

    bool operator!=(const FixedString& fixedString) const {
        return !std::equal(charStr, charStr+MAX_KEY_LEN, fixedString.charStr);
    } 
};

struct comp_type : public std::less<FixedString> {
    static FixedString max_value()
    {
        FixedString s;
        std::fill(s.charStr, s.charStr+MAX_KEY_LEN, 0x7f);
        return s;
    } 
};

请注意,所有的主要运营商(()==,=!)需要被重写所有stxxl ::地图功能,现在的工作,我们可以定义fixed_name_map在地图如下:

typedef stxxl::map<FixedString, unsigned int, comp_type, DATA_NODE_BLOCK_SIZE, DATA_LEAF_BLOCK_SIZE> fixed_name_map;
fixed_name_map myFixedMap((fixed_name_map::node_block_type::raw_size)*5, (fixed_name_map::leaf_block_type::raw_size)*5);

现在该程序编译细且正在接受大约10 ^ 8个串没有任何问题。 我们也可以用myFixedMap比如std ::地图本身。 {用于离:myFixedMap [fixedString] = 10}



Answer 3:

如果使用的是C ++ 11,然后作为替代可以使用的FixedString类std::array<char, MAX_KEY_LEN> 这是一个普通的固定大小的数组c的顶部,因为你是从的std :: string用于实施比较和迭代器的STL层,但它是一个POD类型 ,所以STXXL应该支持。

或者,也可以在使用serialization_sort TPIE 。 它可以排序类型的元素std::pair<std::string, unsigned int>就好了,所以如果你需要的是插入散装一切,然后访问它散装,这将是足以让你的情况(也可能快视具体情况)。



文章来源: How to use std::string as key in stxxl::map