重载 operator[] 运算符?

7
“好的,我正在尝试创建一个快速的小类,作为一种哈希表。如果我能让它工作,那么我应该能够做到这一点:”
  StringHash* hash = new StringHash;
  hash["test"] = "This is a test";
  printf(hash["test"]);

这段话的意思是:“它应该打印出“This is a test”。从目前情况看,我有两个问题。首先,我做了以下操作:”
const char* operator[](const char* key) {
  for(int i = 0; i < hashSize; ++i) {
    if(strcmp(hkeys[i], key) == 0) {return values[i];}
  }
  return NULL;
}

但是当我尝试查找一个值时,编译器会抱怨:
错误:数组下标无效的类型“StringHash *[const char[5]]”
其次,operator [] 似乎不是正确的语法。我能找到的唯一其他东西是 &operator[],但我认为那不会起作用,因为我必须编写查找过程?(这种语法不仅仅用于返回数组项引用吗?)
我在这里尝试做的事情有可能吗?任何建议都将不胜感激。 :)
似乎有些混淆了我想做什么。我会发布我的代码:

http://pastebin.com/5Na1Xvaz


所有帮助完成后的成品:

http://pastebin.com/gx4gnYy8

8个回答

7
错误是因为hash是一个指针。更改为:
StringHash hash;

很好的发现。谢谢你。现在它不会在那里给出编译错误了。初始测试成功,所以我现在可以通过它们的键在哈希中查找值。 - Khat

6
其他答案与你的第一个问题有关。至于你的第二个问题...
如果返回一个引用,那么就返回一个左值。你总是可以将左值赋值给它。
是的,它(几乎)确实如此简单。我建议仔细阅读各种地方是否需要使用const。
我记得读到过,你应该为operator[]提供一个const和非const重载,像这样:
MyType const &operator[](int index) const; // This is the array access version (no assignment allowed), which should work on const objects
MyType &operator[](int index);      // This is the array access or assignment version, which is necessarily non-const.

请查看此链接获取更多信息。

3

hash 不是一个 StringHash 对象,而是指向该对象的指针。

你可以这样做:

(*hash)["test"] = "This is a test";

或者你可以问问自己为什么需要首先拥有它的指针。

StringHash hash;
hash["test" = "This is a test";

如果您不使用智能指针,或者即使您使用,也为什么不使用像auto_ptr这样的智能指针。

#include <memory>
std::auto_ptr<StringHash> hash( new StringHash );
(*hash)["test"] = "This is a test";

3
第一个错误是您声明了hash为指针。指针类型已经可以与索引运算符一起使用。例如,pointer[3]等同于*(pointer+3)。您无法更改此行为。将hash作为对象本身:
StringHash sh;

关于operator[]=,不存在这样的东西。你的索引运算符应该只返回一个引用来使赋值工作。下面是一个简单的例子:

class Indexable
{
   std::string arr[3];
public:
   std::string & operator[](int index) {
      return arr[index];
   }
   std::string const& operator[](int index) const {
      return arr[index];
   }
};

3
请使用 StringHash hash; 代替 new。C++ 不是 Java。 :-)

3

五个问题:

  1. hash是指向StringHash的指针,您必须对其进行解引用才能使用运算符:(*hash)["test"]
  2. 如果要分配给元素,必须返回对元素类型的引用

    const char *& operator[] (const char* key);

    // ...

    (*hash)["test"] = "This is a test"; // 现在将编译

  3. null不是C++中的关键字。请使用0或NULL

  4. operator []必须为找不到的元素分配空间。返回NULL不是一个选项。否则,尝试对(*hash)["test"]的结果进行分配将导致程序崩溃。
  5. 使用std::map或std::tr1::unordered_map而不是编写自己的“快速”类。

只是为了刁难一下:你知道那不是哈希表,对吧?


  1. 已修复。谢谢。
  2. 我正在尝试重载元素赋值,因为我想要将rval进行strcpy操作。
  3. 发帖后注意到了这一点。已修复。谢谢。
  4. 见第2条。
  5. 不想这样做。 :)
为什么它不是哈希表?
- Khat
@ddd:它不是哈希表,因为它不计算键的哈希值以便索引到数组中。请参见http://en.wikipedia.org/wiki/Hash_table。 - Steve M
啊,我明白你的意思了。那就是一个普通的表格吧。 - Khat

3
我首先要问的是,为什么在已经有一些版本可用的情况下你还要编写自己的HashMap,尽管它不是标准的?(这是2010年写的,但现在有std::unordered_map) 你的哈希映射表存储const char *指针还是std::string?(如果它只是一个查找表,用于存储在其他地方存储的数据,而且不会改变其生命周期,那么它可能存储const char*指针。)
当找不到该项时,operator[]应该做什么?
现在让我假设答案是:
  • 是的,我们存储const char *指针,并在空单元格中存储NULL
  • 当我们执行hash[key]=value时,我们想将key与value关联起来
  • 如果我们只是执行hash[key]但没有写入,则不会插入
这可以通过一个神奇的对象来实现:当您向此对象分配const char *时,它会插入或覆盖哈希。您还可以从该对象隐式转换为const char *以进行读取。
不过,这相当复杂,最好坚持使用map的常规接口:operator[]始终插入,而您使用不同的方法来查找。

嗯...我想我明白你的意思了。你希望我编写一个带有operator=()的类,然后让它处理将条目添加到表中,是吗?我可以看到这个方法可行。但我担心的是,我是否需要在内部存储另一个数组,以保存该类的每个实例...啊,不对。我可以只使用这些对象作为内部值,而不是const char*,然后在查找时返回字符串。懂了。 :) - Khat
1
您可以在“magic”类型和const char *之间定义隐式转换。但是,使用std::strings是更稳健的解决方案。 - Steve M
是的,我卡在这里了。我该如何定义一个到const char*的隐式转换?我现在正在尝试查找相关信息。 - Khat
1
我找到了一个网站,上面说要使用“operator const char*()”。我现在正在尝试调整它。(以前从未见过类型作为运算符。) - Khat
1
现在你已经完成了这个任务,接下来的练习是使它成为const-correct。为了实现这一点,如果你有一个对哈希表的const引用,它将允许你读取但不允许插入。提示:operator[]应该有两个重载版本,其中const版本会给你一个真正的const char *。 - CashCow
显示剩余3条评论

1
你能使用 boost::unordered_map<std::string, std::string 吗?这样你就不必自己实现了。
假设这是你自己的练习: 你可能来自不同的背景,但在 C++ 中声明哈希的正常方式是:
StringHash hash;

此外,您的operator[]可能适用于打印,但不适用于赋值。通常,operator[]方法通过返回非const引用或代理对象来工作,新值可以分配给该对象,而您的方法都没有。如果您能够使用std::string,您可以重写您的方法,以返回对应该读取或分配的哈希位置的非const引用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接