оператор [] = перегрузка? - PullRequest
       18

оператор [] = перегрузка?

6 голосов
/ 11 октября 2010

Хорошо, я пытаюсь сделать небольшой урок для работы в качестве своего рода хэш-таблицы. Если я смогу заставить его работать, я смогу сделать это:

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

И это должно распечатать "Это тест".

Похоже, у меня 2 проблемы на данный момент. Сначала я сделал это:

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 [], но я не думаю, что это сработает, поскольку мне нужно кодировать процедуру поиска ??? (Разве этот синтаксис не используется только для возврата ссылки на элемент массива?)

Возможно ли то, что я пытаюсь сделать здесь? Любой совет приветствуется. :)


Кажется, я не совсем понимаю, что я пытаюсь сделать. Я выложу свой код:

http://pastebin.com/5Na1Xvaz


Готовый продукт после всей помощи:

http://pastebin.com/gx4gnYy8

Ответы [ 8 ]

6 голосов
/ 11 октября 2010

Ошибка в том, что hash является указателем. Изменить на:

StringHash hash;
4 голосов
/ 11 октября 2010

Другие ответы относятся к вашему первому вопросу. Что касается вашего второго ...

Если вы возвращаете ссылку, вы возвращаете lvalue. Вы всегда можете присвоить lvalue.

Да, это (в значительной степени) действительно так просто. Я рекомендую внимательно прочитать, нужно ли вам const в разных местах.

Что я помню при чтении, так это то, что вы должны обеспечить const и не- const перегрузку для operator[], что-то вроде этого:

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 голосов
/ 11 октября 2010

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";
2 голосов
/ 11 октября 2010

Сначала я бы задал вопрос, почему вы пишете свой собственный HashMap, когда доступны некоторые версии, хотя и не стандартные.

Хранит ли ваша хеш-карта константные указатели char * или std :: strings? (Он может хранить указатели const char *, если это просто таблица поиска для данных, хранящихся в другом месте, которые не изменят свое время жизни.)

Что должен делать оператор [], когда элемент не найден?

Теперь позвольте мне предположить, что ответы таковы: - Да, мы храним указатели const char * и храним NULL в пустой ячейке. - Когда мы выполняем хэш [ключ] = значение, мы хотим связать ключ со значением - Если мы просто делаем хеш [ключ], но не пишем, он не вставляет

Это можно сделать с помощью магического объекта: когда вы назначаете const char * этому объекту, он вставляет или перезаписывает хеш. Вы также можете иметь неявное преобразование из объекта в const char * для чтения.

Это довольно сложно, хотя предпочтительнее придерживаться обычного интерфейса map: operator [] всегда вставляет, и вы просто используете другой метод для поиска.

2 голосов
/ 11 октября 2010

Пять проблем:

  1. hash - это указатель на StringHash, вы должны разыменовать его, чтобы использовать операторы: (*hash)["test"]
  2. Если вы хотитеПрисвоить элемент необходимо вернуть ссылку на тип элемента

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

    // ...

    (*hash)["test"] = "This is a test"; // will compile now

  3. null не является ключевым словом в C ++.Использование 0 или NULL.

  4. operator [] должно выделить место для элемента, если он не найден.Возврат NULL не вариант.В противном случае попытка присвоить результату (*hash)["test"] приведет к сбою вашей программы.
  5. Используйте std :: map или std :: tr1 :: unordered_map вместо написания собственного "быстрого" класса.

И просто чтобы быть придурком: Вы знаете, что это не хэш-таблица, верно?

2 голосов
/ 11 октября 2010

Первая ошибка в том, что вы объявили хеш указателем.Типы указателей уже могут использоваться с оператором индекса.Например, указатель [3] эквивалентен * (указатель + 3).Вы не можете изменить это поведение.Сделайте хеш для самого объекта:

StringHash sh;

Что касается оператора [] =, такого понятия не существует.Ваш оператор индекса должен просто вернуть ссылку, чтобы сделать назначение работоспособным.Вот простой пример того, как это будет выглядеть:

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];
   }
};
2 голосов
/ 11 октября 2010

Напишите StringHash hash; вместо new. С ++ не Java : -)

1 голос
/ 11 октября 2010

Вы можете использовать boost::unordered_map<std::string, std::string? Тогда вам не нужно беспокоиться об этом самостоятельно.

Предполагая, что это какое-то упражнение для себя: Вы можете иметь различное происхождение, но в C ++ нормальным способом объявить ваш хэш будет:

StringHash hash;

Кроме того, ваш operator[] может работать для печати, но не будет работать для назначения. Обычно operator[] методы работают, возвращая неконстантную ссылку или прокси-объект, которому могут быть назначены новые значения, а ваш - нет. Если бы вы могли использовать std :: string, вы могли бы переписать свой метод так, чтобы он возвращал неконстантную ссылку на позицию в хэше, которую следует прочитать или присвоить.

...