c ++重载下标取消引用,其中允许使用nullptr

时间:2017-07-19 22:47:43

标签: c++ variable-assignment subscript nullptr

您好我是一名学生,为了学习目的而开发各种抽象数据类型。我试图重写下标操作符以查找这些ADT中的键。我无法避免我的代码插入缺失密钥的情况。

当从这些ADT读取时,nullptr的返回值将指示未找到该键。我希望我的ADT只在写入或插入时添加新密钥。我的代码处理以下内容的代码不正确:

const char *x = tree["key"];

如果未找到“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;
}

1 个答案:

答案 0 :(得分:1)

您希望tree["key"]const char *x = tree["key"];中的行为与tree["key"] = "x";中的行为不同。那是不可能的。语句中子表达式的位置对该子表达式的行为方式没有影响。

如果可以更改下标运算符的返回类型,则可能会实现与您正在寻找的行为类似的行为。如果你永远不会将缺少的值添加到树中,并返回一些对象,其行为是在赋值时添加元素(如果缺少),那么你可以使用上述两个语句来表现你喜欢的行为。

尽管如此,以上可能很难实施,可能会有一些警告。也许你不需要能够使用operator[]查找对象而不插入miss。不要试图使用重载,而是使用单独的函数来完成它,比如保罗所建议的std::map