C++ c++;重载允许null ptr的下标解引用
嗨,我是一名学生,为学习目的开发各种抽象数据类型。我正在尝试重载下标操作符以查找这些ADT中的键。我无法避免代码插入缺失键的情况 从这些ADT读取时,返回值为nullptr表示未找到密钥。我希望我的ADT仅在写入或插入时添加新键。我的代码处理以下内容的方式不正确:C++ c++;重载允许null ptr的下标解引用,c++,variable-assignment,subscript,nullptr,C++,Variable Assignment,Subscript,Nullptr,嗨,我是一名学生,为学习目的开发各种抽象数据类型。我正在尝试重载下标操作符以查找这些ADT中的键。我无法避免代码插入缺失键的情况 从这些ADT读取时,返回值为nullptr表示未找到密钥。我希望我的ADT仅在写入或插入时添加新键。我的代码处理以下内容的方式不正确: const char *x = tree["key"]; 在这里,如果找不到“key”,我希望避免添加此key,并返回nullptr以指示其不存在。仅在以下情况下才应添加密钥: tree["key"] = "x"; 这是一个非常微
const char *x = tree["key"];
在这里,如果找不到“key”,我希望避免添加此key,并返回nullptr以指示其不存在。仅在以下情况下才应添加密钥:
tree["key"] = "x";
这是一个非常微妙的错误。下面的测试返回true,但这仅仅是因为被测试的值是hash[“key”].val(恰好为null)
我相信这可以通过使用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;
}
#包括
#包括
类查找{
查找*左;
查找*右;
字符*键;
char*val;
公众:
查找(字符*k){
左=空PTR;
右=空PTR;
val=nullptr;
key=newchar[strlen(k)+1];
strcpy(键,k);
}
~lookup(){
如果(键)删除键;
如果(val)删除val;
}
/*读/写访问*/
/*如果密钥不存在,则创建它*/
字符*&运算符[](字符*索引){
printf(“[]=x\n”);
int x=strcmp(索引,键);
if(x<0){
if(left==nullptr)left=新查找(索引);
返回(*左)[索引];
}
如果(x>0){
if(right==nullptr)right=新查找(索引);
返回(*右)[索引];
}
返回val;
}
/*只读访问*/
/*如果密钥不存在,则返回nullptr(未找到)*/
字符常量*运算符[](字符*索引)常量{
printf(“x=*[]\n”);
int x=strcmp(索引,键);
if(x<0){
if(left==nullptr)返回nullptr;
否则返回(*左)[索引];
}
如果(x>0){
if(right==nullptr)返回nullptr;
否则返回(*右)[索引];
}
返回val;
}
};
内部主(空){
查找树(“根”);
/*这将创建密钥(这不是预期的)*/
const char*x=树[“键”];
如果(!x)printf(“%s未找到!\n”,“key”);
/*现在才应该创建密钥*/
树[“键”]=“值”;
返回0;
}
您希望树[“键”]
在const char*x=tree[“键”]中表现不同代码>比树[“key”]=“x”中的代码>多代码>。这是不可能的。子表达式在语句中的位置对该子表达式的行为没有影响
如果您可以更改下标运算符的返回类型,那么您可能会实现类似于您正在寻找的行为。如果从不向树中添加缺少的值,并返回某个对象,该对象的行为是在赋值时添加元素(如果缺少),则可以使用上述两条语句来实现任意行为
这就是说,上述措施可能很难实施,而且可能存在一些警告。也许您不需要使用操作符[]
来查找对象而不插入未命中。与其尝试使用重载,不如使用一个单独的函数来完成,如Paul建议的std::map
。请注意,如果使用new[]
分配某个对象,则必须使用delete[]
将其释放。如果您使用std::strings而不是C样式的字符串,那么您的代码将更加清晰和简单。if(key)delete key代码>--错误的删除形式
。它应该是delete[]
。避免这种情况,只需使用std::string
。永远不会调用此常量重载。-将lookup
作为常量引用传递给函数,并尝试在该函数内调用lookup::operator[]
。编译程序别无选择,只能调用const
版本。还要注意std::map::operator[]
如果不存在,则插入一个值。这就是为什么如果您不希望这种行为,并且存在诸如map::insert()
之类的函数,就不调用它。为什么不以类似的方式设计类呢?@PaulMcKenzie我看不出std::map
在这里有什么关系。它没有被使用。
#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;
}