У меня очень странная проблема использования самоопределенной хэш-функции в std :: unordered_map.Hash a std :: array, который используется в std :: unordered_map
Мой ключ больше, чем int64, поэтому я использую std :: array для его представления. Чтобы получить его хэш-значение, я создаю класс MyHash:
class MyHash
{
public:
std::size_t operator()(const std::array<char, 12>& oid) const
{
Convert t;
std::memcpy(t.arr, oid.data(), 12);
std::cout << t.a <<" "<<t.b << std::endl;
return (std::hash<std::int32_t>()(t.a)^(std::hash<std::int64_t>()(t.b) << 1)) >> 1;
}
union Convert {
struct {
std::int32_t a;
std::int64_t b;
};
char arr[12];
};
};
Первое, проверить:
std::array<char, 12> arr = {1,2,3,4,5,6,7,8,9,10,11,12};
MyHash o;
o(arr);
o(arr);
Это нормально. Он печатает те же t.a
и t.b
. Теперь используйте его с станд :: unordered_map:
std::unordered_map<std::array<char, 12>, int, MyHash> map;
std::array<char, 12> arr = {1,2,3,4,5,6,7,8,9,10,11,12};
map.insert(std::make_pair(arr, 1));
auto it = map.find(arr);
if(it == map.end())
std::cout << "error";
else
std::cout << it->second;
Теперь он будет печатать error
, причиной этого является t.b
в вставке отличается с находкой. И это только произойдет в режиме выпуска против (или г ++ O2)
Я предпочел бы вычислить хэш всех 12 байтов, используя, например, 'boost :: hash_range': http://coliru.stacked-crooked.com/a/cddb1ea79a18d0b1 –
Сначала я использую его, но я нашел, что он немного медленный, потому что он будет делать 12-кратный хэш.И качество не очень хорошее из-за первых 4 байтов в массиве, почти такое же значение – jean
, если первые 4 байта всегда одинаковы, вы можете просто пропустить их при вычислении хэша ('boost :: hash_range (oid.begin() +4, oid.end()); '); Вы измерили разницу во времени? насколько медленнее это, чем ваш подход memcpy/union? –