Разыменование индексов при перегрузке C++, где разрешено nullptr
Привет, я студент, разрабатывающий различные абстрактные типы данных для целей обучения. Я пытаюсь перегрузить оператор индекса, чтобы найти ключи в этих ADT. Я не могу избежать случая, когда мой код вставляет недостающие ключи.
Предполагается, что при чтении из этих ADT возвращаемое значение nullptr будет указывать, что ключ не был найден. Я хочу, чтобы мои ADT добавляли новые ключи только при записи или вставке. Мой код неверен в том, как он обрабатывает следующее:
const char *x = tree["key"];
Здесь, если "ключ" не найден, я хочу избежать добавления этого ключа и вернуть nullptr, чтобы указать его отсутствие. Ключ следует добавлять только в следующей ситуации:
tree["key"] = "x";
Это очень тонкая ошибка. Следующий тест возвращает true, но только потому, что проверяемым значением является hash["key"]. Val (который имеет значение null).
if (!x) printf("%s not found!\n", "key");
Я считаю, что это может быть достигнуто с помощью const и использовать следующую подпись.
char const *operator[](char *index) const;
Эта постоянная перегрузка никогда не вызывается. Может кто-нибудь объяснить, почему это так, и пример сигнатуры, которая будет вести себя должным образом (или пример, который заставит эту перегрузку быть оцененной). Вот мой код:
#include <stdio.h>
#include <string.h>
class lookup {
lookup *left;
lookup *right;
char *key;
char *val;
public:
lookup(char *k) {
left = nullptr;
right = nullptr;
val = nullptr;
key = new char[strlen(k)+1];
strcpy(key, k);
}
~lookup() {
if (key) delete key;
if (val) delete val;
}
/* read/write access */
/* if the key does not exist, then create it */
char *&operator[](char *index) {
printf(" []= x\n");
int x = strcmp(index, key);
if (x < 0) {
if (left == nullptr) left = new lookup(index);
return (*left)[index];
}
if (x > 0) {
if (right == nullptr) right = new lookup(index);
return (*right)[index];
}
return val;
}
/* read only access */
/* if the key does not exist, then return nullptr (not found) */
char const *operator[](char *index) const {
printf(" x = *[]\n");
int x = strcmp(index, key);
if (x < 0) {
if (left == nullptr) return nullptr;
else return (*left)[index];
}
if (x > 0) {
if (right == nullptr) return nullptr;
else return (*right)[index];
}
return val;
}
};
int main(void) {
lookup tree("root");
/* this creates the key (which is not intended) */
const char *x = tree["key"];
if (!x) printf("%s not found!\n", "key");
/* only now should the key be created */
tree["key"] = "value";
return 0;
}
1 ответ
Ты хочешь tree["key"]
вести себя по-другому в const char *x = tree["key"];
чем в tree["key"] = "x";
, Это просто невозможно. Положение подвыражения в выражении не влияет на поведение этого подвыражения.
Вы можете достичь поведения, аналогичного тому, которое вы ищете, если вы можете изменить тип возврата оператора индекса. Если вы никогда не добавляете отсутствующее значение в дерево и возвращаете какой-либо объект, поведение которого заключается в добавлении элемента (если он отсутствует) при присваивании, тогда вы можете использовать операторы "два выше", чтобы вести себя как вам угодно.
Тем не менее, вышеизложенное может быть сложно реализовать, и могут быть оговорки. Возможно, вам не нужно уметь использовать operator[]
искать объект, не вставляя на мисс. Вместо того, чтобы пытаться использовать перегрузку, было бы проще использовать отдельную функцию, например std::map
который предложил Павел.