C++重载下标解除引用,其中允许nullptr
问题描述:
嗨,我是一名学生,为学习目的开发各种抽象数据类型。我想重载下标操作符来查找这些ADT中的键。我无法避免我的代码插入缺少的键的情况。C++重载下标解除引用,其中允许nullptr
当从这些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;
这个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;
}
答
你想tree["key"]
不同的行为在const char *x = tree["key"];
比tree["key"] = "x";
。这是不可能的。子表达式在语句中的位置对该子表达式的行为没有影响。
如果您可以更改下标操作符的返回类型,您可能会实现与所查找内容类似的行为。如果你永远不会将缺失的值添加到树中,并返回一些对象的行为是在赋值时添加元素(如果缺少),那么可以使用上面的两个语句来表现你喜欢的行为。
这就是说,上述可能会很棘手的实施,并可能有警告。也许你不需要能够使用operator[]
查找一个对象,而不会错过插入。与其试图使用重载,不如使用单独的函数来执行它,比如Paul建议的std::map
。
请注意,如果您使用'new []'分配内容,则必须使用'delete []'释放它。如果你使用std :: string而不是C风格的字符串,你的代码会更清晰和简单。 –
'if(key)delete key;' - 错误形式的'delete'。它应该是'delete []'。避免这一点,只使用'std :: string'。 – PaulMcKenzie
*这个const超载从不被调用* - 将'lookup'作为一个const引用传递给一个函数,并尝试调用该函数内的'lookup :: operator []'。编译别无选择,只能调用'const'版本。 – PaulMcKenzie