字典的[]运算符如何知道是否正在引用或分配它?

时间:2019-12-23 19:09:51

标签: c++ dictionary hash operator-overloading

#ifndef _LIBCPP_HASH
#define _LIBCPP_HASH

#include <iostream>
#include <string>
#include <string.h>
#include <iomanip>
#define PERTERB_SHIFT 5
using namespace std;

int FAIL = 0;

template <typename myType>
class HashMap
{
  public:

    HashMap()
    {
      Size = 8;
      Resize = 2;
      Keys = new int[8];
      Values = new myType[8];
      typesize = sizeof(myType);
      Fill = 0;
      memset(Keys, -1, 32);
      memset(Values, 0, 8 * typesize);
    }

    ~HashMap()
    {
      delete[] Keys;
      delete[] Values;
    }

    HashMap(const HashMap &table)
    {
      Size = table.Size;
      Keys = table.Keys;
      Values = table.Values;
    }

    int GetSize() { return Size; }
    // can't return get(key) because no binding of reference int to temporary int, so has the same body as get..
    myType &operator[] (int hash)
    {
      register size_t perterb = hash;
      register unsigned long j = 0;
      register int temp = 0;
      register int index = 0;
      while ( Keys[index] != hash && Keys[index] != -1)
      {
        j = 5 * j + 1 + perterb;
        perterb >>= PERTERB_SHIFT;
        index = j % (2 << Resize);
        //cout << "j : " << j << " temp: " << temp << " hash: " << hash << " index: " << index << endl;
      }

      if (Fill == (int)(Size * 2 / 3))
      {
        cout << "here" << endl;
        Resize <<= 1;
        int* tempkey = new int[Size*2];
        myType* tempvalue = new myType[Size*2];
        memset(tempkey, -1, Size*8);
        memset(tempvalue, 0, Size*2*typesize);
        copy(Keys, Keys + Size, tempkey);
        copy(Values, Values + Size, tempvalue);
        delete[] Values; delete[] Keys;
        Keys = tempkey; Values = tempvalue;
        Size <<= 1;
      }
      if (Keys[index] != hash) Fill ++;
      Keys[index] = hash;
      return Values[index];

    }

    bool insert(int key, myType value)
    {
      int index = key % Size;
      short temp = 0;
      while ((Keys[index] != key) && (Keys[index] != -1) && temp < Size)
      {
        index ++;
        temp ++;
      }
      if (temp == Size)
      {
        int s = static_cast<int>(Size*4);
        int* tempkey = new int[s];
        myType* tempvalue = new myType[s];
        for (int i = Size; i < s; i++)
        {
          tempkey[i] = -1;
          tempvalue[i] = 0;
        }
        copy(Keys, Keys + Size, tempkey);
        copy(Values, Values + Size, tempvalue);
        delete[] Values; delete[] Keys;
        Size *= 4;
        Keys = tempkey;
        Values = tempvalue;
      }
      Keys[index] = key;
      Values[index] = value;
      return true;
    }

    myType get(int key)
    {
      int index = key % Size;
      short count = 0;
      while (Keys[index] != key && count < Size)
      {
        index ++;
        count ++;
      }
      if (count == Size)
      {
        try
        {
          throw key;
        }
        catch (int er)
        {
          cout << "KeyError: " << er << endl;
        }
        return FAIL;
      }
      return Values[index];
    }

    myType pop(int key)
    {
      int index = key % Size;
      short count = 0;
      while (Keys[index] != key && count < Size)
      {
        index ++;
        count ++;
      }
      if ( count == Size )
      {
        try
        {
          throw key;
        }
        catch (int er)
        {
          cout << "KeyError: " << er << endl;
        }
        return FAIL;
      }
      myType temp = Values[index];
      Values[index] = 0;
      Keys[index] = -1;
      return temp;
    }

    void Print()
    {
      cout << "index\t" << "key\t" << "value\t" << endl;
      for (int i = 0; i < Size; i++)
      {
        cout << i << "\t" << Keys[i] << "\t" << Values[i] << "\t" << endl;
      }
    }
  private:
    int Size;
    int Resize;
    int* Keys;
    myType* Values;
    short typesize;
    int Fill;
};

#endif

这是我目前的代码。哈希函数基于Python字典。插入哈希表条目后尝试引用该条目时会出现此问题。如果在插入过程中发生冲突,则[]运算符会将引用视为试图再次插入该值,并将在第一个键= -1处停止,而不是进行迭代直到在键数组中找到哈希值为止。我可以通过insert(),pop()和get()解决此问题,但是我不知道如何为[]运算符处理它,因为它既用于引用又用于赋值。在尝试插入或获取散列之前,它需要知道是否在赋值运算符之后。

我花了一些时间在Python源代码中试图弄清楚他们如何处理此问题,但我无法弄清楚。

我知道这是一个奇怪的问题,但我将非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您的[]可以返回代理类型,该代理类型又具有operator int()&&用于读取和operator =(int const&)&&用于写入。

存在一些问题,因为它与auto的互动较差,但确实可以正常工作。

这是std向量bool为支持位压缩数据所做的工作。人们认为这是一个错误,但部分原因是不相关的。