hash_multimap找不到它应该的方式

时间:2013-05-30 06:45:34

标签: c++ find multimap hash-function

我一直在尝试使用hash_multimap,但是find方法一直给我一个迭代器到容器的末尾,即使我知道它找到了一个匹配的键。让我感到困惑的是,我之前使用过相同的代码来完成一个不同的项目,它完美地工作但现在它正在播放。我知道它找到的东西的原因是因为我在哈希函数和哈希比较中放了几个cout,这告诉我找到了一个键并且它与我给hash_multimap :: find meathod相匹配,但它仍然是给了我一个迭代器。

首先是头文件

//
//  HashGrid.h
//  Planetarium
//
//  Created by Taura J Greig on 24/08/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef _HASHGRID_
#define _HASHGRID_

#include <iostream>
#include <hash_map>
#include <deque>
#include "..//hashKey.h"


struct myTraits
{
    static const size_t bucket_size = 4;
    static const size_t min_buckets = 8;

    myTraits() { };

    myHash hashfunction;
    myEqualTo equal_to;

    size_t operator() (const hashKey& key) const
    {
        size_t hashval = 0;
        hashval = ((key.y * globalGridWidth) + key.x);

        cout << "x : " << key.x << " y : " << key.y << endl;
        cout << "hashVal : " << hashval << endl;

        return hashval;
    }

    bool operator() (const hashKey& key1, const hashKey& key2) const
    {
        bool test = (key1.x == key2.x && key1.y == key2.y);
        cout << "equal_to = " << test << endl;
        return test;
    }
};

using namespace std;
//using namespace stdext;


using namespace stdext;

template <class T>
class HashGrid
{
public:
    typedef deque<T *> localObjects;
    typedef pair<hashKey, T *> addingPair;
    typedef hash_multimap <hashKey, T *, myTraits> hashmMap;
    typedef typename hash_multimap <hashKey, T *, myTraits> :: iterator hashmMapItor;
    typedef pair<hashmMapItor, hashmMapItor> valueRange;

private:

    hashKey keyOffsets[9];

    int gridSize;
    hash_multimap<hashKey, T*, myTraits> theMap;

    inline bool exists(hashKey & theKey);
    inline bool exists(hashKey & theKey, hashmMapItor & it);
public:
    HashGrid();

    void setup(int gridSize);
    void update();
    void draw(); // this is used for viusal debug,

    void resize();

    void addObject(T * object);

    void getLocalObjects(float & x, float & y, int range, localObjects & p1);

};

template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey)
{
    hashmMapItor it;
    it = theMap.find(theKey);
    if (it == theMap.end())
    {
        return false;
    }
    else
    {
        return true;
    }
}

template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey, 
                                      hashmMapItor & it)
{
    it = theMap.find(theKey);
    if (it == theMap.end())
    {
        return false;
    }
    else
    {
        return true;
    }
}

#include "HashGrid.cpp"

#endif

和源文件

//
//  HashGrid.cpp
//  Planetarium
//
//  Created by Taura J Greig on 26/08/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef _HASHGRID_SOURCE_
#define _HASHGRID_SOURCE_

#include "HashGrid.h"
#include "ofMain.h"


template<class T>
void HashGrid<T>::update()
{
    theMap.clear();
}

template <class T>
void HashGrid<T>::addObject(T *obj)
{
    hashKey tempKey;
    tempKey.x = int(obj -> getPos().x) / gridSize;
    tempKey.y = int(obj -> getPos().y) / gridSize;

    cout << "tempKey.x : " << tempKey.x  << endl;
    cout << "tempKey.y : " << tempKey.y  << endl;

    theMap.insert(addingPair(tempKey, obj));
}

template <class T>
void HashGrid<T>::getLocalObjects(float & x, float & y, int range, localObjects & p1)
{
    cout << "you are gettin local objects" << endl; 

    int gridX = (int(x) / gridSize);
    int gridY = (int(y) / gridSize);

    cout << "player x : " <<  x << endl;
    cout << "player y : " <<  y << endl;
    cout << "girdX " << gridX << endl;
    cout << "girdY " << gridY << endl;


    for (int i = 0; i < 9; i++)
    {
        hashKey tempkey;    

        tempkey.x = gridX;
        tempkey.y = gridY;

        tempkey += keyOffsets[i];

        cout << i << " tempKey : " << tempkey.x << " " << tempkey.y << endl;

        cout << "exists " << exists(tempkey) << " ";

            //this is where the problem lies, the exists function will always return 
            //false even when the key is found
        if (exists(tempkey)) 
        {
            cout << "found" << endl;

            hashmMapItor it;
            valueRange elements;

            elements = theMap.equal_range(tempkey);
            for (it = elements.first; it != elements.second; it++)
            {
                p1.push_back(it->second);

            }
        }
        else
        {
            cout << "not found" << endl;
        }
    }
}

#endif

请注意,我已经从上面的块中删除了很多方法以节省空间,因为它们与手头的问题无关。但是我已经在头文件中留下了他们的声明。此外,我知道我正在使用丑陋的模板做一些事情。现在就处理它。

现在我将详细介绍代码中发生的问题以及问题所在。在getlocalobjects方法中,调用方法“exists(key)”以确定hash_multimap是否具有提供密钥的元素。我知道它确实找到了一些东西,因为正如我上面提到的,因为我把cout放在equal_to函数中告诉我它何时使用了它的结果。

一直它告诉我是(通过equal_to debug)它找到了一些东西,但是exists方法仍然会返回false。这让我相信hash_multimap :: find中可能存在一个错误,因为它意味着即使它找到了它给我一个hash_multimap :: end的迭代器

所以我的问题是我在使用multimap时做得非常糟糕吗?我的特征结构没有多图表正常工作所需的东西

编辑以及我忘记的hashKey的实现包括

#ifndef _HASHKEY_
#define _HASHKEY_

#include <iostream>

using namespace std;

static int globalGridSize = 1;

static int globalGridWidth = 1;
static int globalGridHeight = 1;

struct hashKey
{
public:
    int x;
    int y;

    hashKey();
    hashKey(int x, int y);

    void set(int x, int y);
    void set(hashKey & key);

    void printKey()
    {
        cout << x << " " << y <<  endl;
    }

    bool operator < (const hashKey & key1) const;

    bool operator == (const hashKey & key1) const;

    hashKey& operator += (hashKey & key1);
};

#endif

和来源

#ifndef _HASHKEY_SOURCE_
#define _HASHKEY_SOURCE_

#include "hashKey.h"

hashKey::hashKey()
{
    x = 0;
    y = 0;
}

hashKey::hashKey(int x, int y)
{
    hashKey::x = x;
    hashKey::y = y;
}

void hashKey::set(int x, int y)
{
    hashKey::x = x;
    hashKey::y = y;
}

void hashKey::set(hashKey &key)
{
    x = key.x;
    y = key.y;
    cout << "set: x = " << x << " y = " << y << endl; 
}

bool hashKey::operator<(const hashKey &key1) const
{
    if ( (this->x < key1.x) && (this->y < key1.y))
    {
        return true;
    }
    return false;
}

bool hashKey::operator == (const hashKey &key1) const
{
    if ((this-> x == key1.x) && (this->y == key1.y))
    {
        return true;
    }
    return false;
}

hashKey& hashKey::operator+=(hashKey &key1)
{
    this->x += key1.x;
    this->y += key1.y;
    return *this;
}

#endif

编辑[SOVLED]我将hash_multimap tp更改为unordered_multimap,现在它正常工作,因此最初的怀疑是正确的,此时hash_multimap被窃听,其find方法将始终给出结尾的迭代器。请注意,我正在使用visual studio c ++ 2010,它可能不会在其他平台或其他编译器上被窃听,但是在我的情况下它会被挑剔

1 个答案:

答案 0 :(得分:0)

以下内容是推测,因为并非所有相关代码都可见。

好像你有:

  • 类型为size_t的哈希(从operator()的第一个myTraits创建)
  • 类型为hashKey的键(不是hash_multimap的哈希值)

您没有提供hashKey的实施,所以我的直接问题是:

  • 您是否为hashKey
  • 提供了相等运算符
  • 或者,您是否覆盖了equal_to<haskHey>

我看到的潜在问题(以及上述问题的原因)是您将hashmMap定义为hash_multimap <hashKey, T *, myTraits>,它会覆盖散列函数,但覆盖密钥相等(类型为hashKey)。所以,我假设可以使用hashKey的默认比较器(而不是myTraits中定义的比较器)。 也许hash_multimap <hashKey, T *, myTraits, myTraits>就足够了?


更新:我注意到VS&#39; hash_multimap的签名与STL签名不同。比较:

后者具有散列函数和关键比较器分离。一旦你切换编译器,这只是要求一些可怕的问题!