gpt4 book ai didi

c++ - 如何使用 boost::unordered_map

转载 作者:行者123 更新时间:2023-11-30 02:11:02 26 4
gpt4 key购买 nike

对于我的应用程序,我需要使用 HashMap ,因此我编写了一个测试程序,其中我将一些基类实例存储在 boost::unordered_map 中。但我想通过调用返回基的派生类的特殊函数来访问实例,我将这些函数的参数用于 unordered_map 的哈希键。如果没有找到具有某些参数的类,则生成一个类并将其存储在 map 中。该程序的目的可能不清楚,但这是代码。

#include <boost/unordered_map.hpp>
#include <iostream>

using namespace std;
using namespace boost;
typedef unsigned char BYT;
typedef unsigned long long ULL;

class BaseClass
{
public:
int sign;
size_t HASHCODE;
BaseClass(){}
};

class ClassA : public BaseClass
{
public:
int AParam1;
int AParam2;
ClassA(int s1, int s2) : AParam1(s1), AParam2(s2)
{
sign = AParam1;
}
};


struct HashKey
{
ULL * hasharray;
size_t hashNum;
size_t HASHCODE;
HashKey(ULL * ULLarray, size_t Hashnum) : hasharray(ULLarray), hashNum(Hashnum), HASHCODE(0)
{ }
bool operator == (const HashKey & hk ) const
{
bool deg = (hashNum == hk.hashNum);
if (deg)
{
for (int i = 0; i< hashNum;i++)
if(hasharray[i] != hk.hasharray[i]) return false;
}
return deg;
}
};

struct ihash : std::unary_function<HashKey, std::size_t>
{
std::size_t operator()(HashKey const & x) const
{
std::size_t seed = 0;
if (x.hashNum == 1)
seed = x.hasharray[0];
else
{
int amount = x.hashNum * 8;
const std::size_t fnv_prime = 16777619u;
BYT * byt = (BYT*)x.hasharray;
for (int i = 0; i< amount;i++)
{
seed ^= byt[0];
seed *= fnv_prime;
}
}
return seed;
}
};

typedef std::pair<HashKey,BaseClass*> HashPair;
unordered_map<HashKey,BaseClass*,ihash> UMAP;
typedef unordered_map<HashKey,BaseClass*,ihash>::iterator iter;


BaseClass * & FindClass(ULL* byt, int Num, size_t & HCode)
{
HashKey hk(byt,Num);
HashPair hp(hk,0);
std::pair<iter,bool> xx = UMAP.insert(hp);
// if (xx.second) UMAP.rehash((UMAP.size() + 1) / UMAP.max_load_factor() + 1);
if (!xx.first->second) HCode = UMAP.hash_function()(hk);
return xx.first->second;
}


template <typename T, class A,class B>
T* GetClass(size_t& hashcode ,A a, B b)
{
ULL byt[3] = {a,b,hashcode};
BaseClass *& cls = FindClass(byt, 3, hashcode);
if(! cls){ cls = new T(a,b); cls->HASHCODE = hashcode;}
return static_cast<T*>(cls);
}



ClassA * findA(int Period1, int Period2)
{
size_t classID = 100;
return GetClass<ClassA>(classID,Period1,Period2);
}

int main(int argc, char* argv[])
{
int limit = 1000;
int modnum = 40;
int result = 0;

for(int i = 0 ; i < limit; i++ )
{
result += findA( rand() % modnum ,4)->sign ;
}

cout << UMAP.size() << "," << UMAP.bucket_count() << "," << result << endl;

int x = 0;

for(iter it = UMAP.begin(); it != UMAP.end(); it++)
{
cout << ++x << "," << it->second->HASHCODE << "," << it->second->sign << endl ;
delete it->second;

}

return 0;
}

问题是,我希望 UMAP 的大小等于 modnum,但它总是大于 modnum,这意味着有不止一个实例具有相同的参数和 HASHCODE。

我的问题的解决方案是什么?请帮助。
谢谢

最佳答案

这里有几个设计问题:

struct HashKey
{
ULL * hasharray;
...

您的键类型存储指向某个数组的指针。但是这个指针是用本地对象的地址初始化的:

BaseClass * & FindClass(ULL* byt, int Num, size_t & HCode)
{
HashKey hk(byt,Num); // <-- !!!
HashPair hp(hk,0);
std::pair<iter,bool> xx = UMAP.insert(hp);
if (!xx.first->second) HCode = UMAP.hash_function()(hk);
return xx.first->second;
}

template <typename T, class A,class B>
T* GetClass(size_t& hashcode ,A a, B b)
{
ULL byt[3] = {a,b,hashcode}; // <-- !!!
BaseClass *& cls = FindClass(byt, 3, hashcode);
if(! cls){ cls = new T(a,b); cls->HASHCODE = hashcode;}
return static_cast<T*>(cls);
}

这使得 map 存储一个带有悬挂指针的 HashKey 对象。此外,您还返回对 FindClass 中名为 xx 的函数局部对象成员的引用。使用此引用会调用未定义的行为。

考虑重命名 map 的键类型。哈希码本身不应该是一个键。正如您的 operator== for HashKey 所建议的那样,您不希望实际 key 是哈希码,而是可变长度的整数序列。此外,考虑将序列存储在键类型中而不是指针中,例如,作为 vector 。此外,避免返回对函数局部对象的引用。

关于c++ - 如何使用 boost::unordered_map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3985836/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com