C++ std::带有自定义键的无序映射在约31000个元素处失败

C++ std::带有自定义键的无序映射在约31000个元素处失败,c++,stl,C++,Stl,我使用自定义键在无序映射中存储指向组件类的指针 (有关这样做的动机,请参阅) 我可以存储多达30000个组件而不会出现问题。当我存储31000个组件时,容器完全无声地失败 (我首先想到的是有符号16位整数的最大值,但在32767处稍大一些) 我怀疑自定义密钥的散列有问题,因为使用标准密钥不会显示此问题。对于这个可行性测试,我不关心性能,所以我使用了一个非常简单且易于理解的哈希函数。我尝试了几个不同的散列函数,但都显示了相同的问题——下面的代码是最简单的 下面的最小完整程序代码的行为与30000个

我使用自定义键在无序映射中存储指向组件类的指针

(有关这样做的动机,请参阅)

我可以存储多达30000个组件而不会出现问题。当我存储31000个组件时,容器完全无声地失败

(我首先想到的是有符号16位整数的最大值,但在32767处稍大一些)

我怀疑自定义密钥的散列有问题,因为使用标准密钥不会显示此问题。对于这个可行性测试,我不关心性能,所以我使用了一个非常简单且易于理解的哈希函数。我尝试了几个不同的散列函数,但都显示了相同的问题——下面的代码是最简单的

下面的最小完整程序代码的行为与30000个组件的预期相同

Map contains 30000
type 12 found type 12 found total 10, OK
Map contains 31000
type 12 found type 12 found total 0, ERROR! Incorrect component count recovered
但对于31000个组件失败

Map contains 30000
type 12 found type 12 found total 10, OK
Map contains 31000
type 12 found type 12 found total 0, ERROR! Incorrect component count recovered
代码如下:

#include <iostream>
#include <sstream>
#include <iomanip>
#include <unordered_map>

#define maxScene 10
#define maxLayer 10
#define maxType 100
#define maxID   10000

#define COUNT_COMPS_FOR_EACH_SCENE_LAYER_TYPE 10

// OK for 30, but fails for 31
#define COUNT_TYPES 31

using namespace std;

class Component
{
public:
    int myID;
    static long long lastID;
    Component()
    {
        myID = ++lastID;
    }
};

long long Component::lastID = -1;

class cKey
{
public:
    size_t scene;
    size_t layer;
    size_t type;
    long long id;

    void Display() const;

};

struct KeyHash
{
public:
    size_t operator()(const cKey & key) const
    {
        std::hash<string> shash;
        stringstream ss;
        ss << setw(3) << key.scene << setw(3)<< key.layer << setw(4) << key.type;
        //key.Display();
        //cout << " " << ss.str() << "\n";
        return shash( ss.str() );
    }
};
struct KeyEqual
{
public:
    bool operator()(const cKey & key1, const cKey & key2) const
    {
        if( key1.scene != key2.scene )
            return false;
        if( key1.layer != key2.layer )
            return false;
        if( key1.type != key2.type )
            return false;
        if( key1.id != key2.id )
            return false;
        return true;
    }
};

void cKey::Display() const
{
    cout << scene <<" "<< layer <<" "<< type <<" "<<id ;
}

int main()
{

    unordered_map< cKey, Component*,
                   KeyHash, KeyEqual  > theMap;

    // store components
    int insertCount = 0;
    cKey key;
    for( key.scene = 0; key.scene < maxScene; key.scene++ )
    {
        for( key.layer = 0; key.layer < maxLayer; key.layer++ )
        {
            // store specified number of types
            for( key.type = 0; key.type < COUNT_TYPES; key.type++ )
            {
                // store specified number of components for this scene, layer and type
                for( int k = 0; k < COUNT_COMPS_FOR_EACH_SCENE_LAYER_TYPE; k++ )
                {
                    insertCount++;
                    Component* pc = new Component;
                    key.id = pc->myID;

                    auto ret = theMap.insert( make_pair( key, pc ));
                    if( ! ret.second )
                    {
                        cout << "insert failed ";
                        key.Display();
                        return 1;
                    }
                }
            }
        }
    }

    cout << "Map contains " << theMap.size() << "\n";

    // iterate over components of one type in a particular scene and layer
    key.scene = 3;
    key.layer = 2;
    key.type  = 12;
    cout << "type " << key.type << " found ";
    int count = 0;
    for( key.id = 0; key.id < maxID; key.id++ )
    {
        auto it = theMap.find( key );
        if( it == theMap.end() )
            continue;
        count++;
    }
    cout << "type " << key.type << " found total "<< count << ", ";
    if( count != COUNT_COMPS_FOR_EACH_SCENE_LAYER_TYPE )
        cout << "ERROR! Incorrect component count recovered\n";
    else
        cout << "OK";

    return 0;
}
#包括
#包括
#包括
#包括
#定义场景10
#定义maxLayer 10
#定义maxType 100
#定义maxid10000
#为每个场景定义计数补偿类型10
//30次可以,但31次失败
#定义计数类型31
使用名称空间std;
类组件
{
公众:
int-myID;
静态长柄;
组件()
{
myID=++lastID;
}
};
长组件::lastID=-1;
卡基班
{
公众:
场景大小;
层的大小;
尺寸类型;
长id;
void Display()常量;
};
结构键哈希
{
公众:
大小\u t运算符()(常数和键)常数
{
std::hash shash;
细流ss;

ss如果您将以下内容写入计数元素的循环

for (key.id = 0; key.id <= Component::lastID; key.id++)
{
    auto it = theMap.find(key);
    if (it == theMap.end())
        continue;
    count++;
}

用于(key.id=0;key.id哇,使用
std::stringstream
创建哈希!效率很难再低了。另请看
std::tie
。为什么id被视为相等的一部分而不是哈希的一部分?@Deduplicator请阅读我对哈希的描述function@ravenspoint抱歉我之前的评论,我不是故意的I don’我不想打扰你,但我正试图理解你在做什么。如果我在for循环中使用key.id@ravenspoint,谢谢!如果我很痛苦,很抱歉,但不应该使用key.id