我应该如何在C++中为此类编写destructor?

发布于 2025-02-08 19:49:43 字数 2519 浏览 2 评论 0原文

我有一个具有这种结构的课程:

class myClass(){
  public:
    myClass(){//empty constructor}
    
    void insertRecursively(string word) {
        myClass* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                node->map[word.at(i)] = new myClass();
            }
            node = node->map[word.at(i)];
        }
        node->isEnd = true;
    }

  
  private:
    unordered_map<char, myClass*> map = {};
    bool isEnd = false;
}

我尝试以这种方式编写destructor,但它给我错误的“ std :: bad_alloc':

~myClass() {
    clear(map);
}

void clear(unordered_map<char, myClass*> map) {
    for (auto& pair : map) {
        if (pair.second != nullptr) {
            clear(pair.second->map);
        }
        delete pair.second;
    }
}

从我到目前为止所知道的,我使用新关键字在堆上分配了内存,所以我应该应该为myclass创建驱动器。我需要递归地这样做,因为地图包含其他myllass指针的指针。

我已经研究了几个小时,但仍然无法弄清楚。 谁能帮助我发现会导致“ std :: bad_alloc”的问题?

我的整个代码:

class Trie {
public:
    Trie() {
    }

    void insert(string word) {
        Trie* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                node->map[word.at(i)] = new Trie();
            }
            node = node->map[word.at(i)];
        }
        node->isEnd = true;
    }

    bool search(string word) {
        Trie* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                return false;
            } else {
                node = node->map[word.at(i)];
            }
        }
        return node->isEnd;
    }

    bool startsWith(string prefix) {
        Trie* node = this;
        for (int i = 0; i < prefix.length(); i++) {
            if (node->map.find(prefix.at(i)) == node->map.end()) {
                return false;
            } else {
                node = node->map[prefix.at(i)];
            }
        }
        return true;
    }

    ~Trie() {
        clear(map);
    }

    void clear(unordered_map<char, Trie*> map) {
        for (auto& pair : map) {
            if (pair.second != nullptr) {
                clear(pair.second->map);
            }
            delete pair.second;
        }
    }

private:
    unordered_map<char, Trie*> map = {};
    bool isEnd = false;
};

I have a class that has this kind of structure:

class myClass(){
  public:
    myClass(){//empty constructor}
    
    void insertRecursively(string word) {
        myClass* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                node->map[word.at(i)] = new myClass();
            }
            node = node->map[word.at(i)];
        }
        node->isEnd = true;
    }

  
  private:
    unordered_map<char, myClass*> map = {};
    bool isEnd = false;
}

I tried write destructor in this way but it gives me error 'std::bad_alloc':

~myClass() {
    clear(map);
}

void clear(unordered_map<char, myClass*> map) {
    for (auto& pair : map) {
        if (pair.second != nullptr) {
            clear(pair.second->map);
        }
        delete pair.second;
    }
}

From what I known so far, I allocated memory on heap by using new keyword, so I should create destructor for myClass. I need to do this recursively because map contains pointers to other myClass pointers.

I've researched several hours and still cannot figure it out.
Can anyone help me to spot the problem that will cause 'std::bad_alloc' ?

My entire code:

class Trie {
public:
    Trie() {
    }

    void insert(string word) {
        Trie* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                node->map[word.at(i)] = new Trie();
            }
            node = node->map[word.at(i)];
        }
        node->isEnd = true;
    }

    bool search(string word) {
        Trie* node = this;
        for (int i = 0; i < word.length(); i++) {
            if (node->map.find(word.at(i)) == node->map.end()) {
                return false;
            } else {
                node = node->map[word.at(i)];
            }
        }
        return node->isEnd;
    }

    bool startsWith(string prefix) {
        Trie* node = this;
        for (int i = 0; i < prefix.length(); i++) {
            if (node->map.find(prefix.at(i)) == node->map.end()) {
                return false;
            } else {
                node = node->map[prefix.at(i)];
            }
        }
        return true;
    }

    ~Trie() {
        clear(map);
    }

    void clear(unordered_map<char, Trie*> map) {
        for (auto& pair : map) {
            if (pair.second != nullptr) {
                clear(pair.second->map);
            }
            delete pair.second;
        }
    }

private:
    unordered_map<char, Trie*> map = {};
    bool isEnd = false;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅沫记忆 2025-02-15 19:49:43

我将注意力集中在以下代码上。

unordered_map<char, myClass*> map = {};
void clear(unordered_map<char, myClass> map)

修剪几个字符...

unordered_map<char, myClass*> map
void clear(unordered_map<char, myClass> map)

观察到您在char和myclass*上声明了本地项目地图,但是您将clear()宣布为在char和myclass上的地图上操作,而不是通过char和myclass*的地图。

*有所作为。

I draw your attention to the following lines of code.

unordered_map<char, myClass*> map = {};
void clear(unordered_map<char, myClass> map)

Trimming a few characters...

unordered_map<char, myClass*> map
void clear(unordered_map<char, myClass> map)

Observe that you declared the local item map over char and myClass*, but you declared clear() as operating on a map over char and myClass, as opposed to a map over char and myClass*.

The * makes a difference.

秉烛思 2025-02-15 19:49:43

您要么开始使用 Smart Pointer ,要么需要提出一个用myClass实例创建的new的概念。

后者可能是:

  • Instances myClass的AmyClass的另一个实例所有(让我们称其为ander> lands)其中&amp; a出现在所有者.map中(您已经在执行此操作)。
  • 每当实例所有者被销毁时,它必须(直接)释放所有实例:
~myClass() {
  for(const auto& pair : map){
    delete pair.second;
  }
}

Either you start to use smart pointers or you need to bring up a concept of ownership for your myClass instances created with new.

The latter could be:

  • Instances aof myClass are owned by another instance of myClass (lets call it owner) where &a appears in owner.map (You are doing this already).
  • Whenever an instance owner becomes destroyed, it has to free all instances it (directly) owns:
~myClass() {
  for(const auto& pair : map){
    delete pair.second;
  }
}
薄暮涼年 2025-02-15 19:49:43

您的trie :: clear()方法两次删除相同的trie

~Trie() {
    clear(map);
}

void clear(unordered_map<char, Trie*> map) {
    for (auto& pair : map) {
        if (pair.second != nullptr) {
            clear(pair.second->map);
        }
        delete pair.second;
    }
}

destructor 〜trie调用clear(pair.second-&gt; map),然后调用delete pair.second.second,与clear(pair.second-&gt; map)由于delete调用指向at数据的删除器。在同一地图上两次呼叫clear()两次意味着第二个调用试图删除已删除的数据,这会导致崩溃。调用delete在指针上不会更改指针的值,这就是为什么nullptr检查检查什么都不做。

由于destructor调用clear(),因此clear()方法无需清楚地递归地调用自己。只需删除地图指针即可。

~Trie() {
    clear(map);
}

void clear(unordered_map<char, Trie*> map) {
    for (auto& pair : map) {
        delete pair.second;
    }
}

顺便说一句,调用删除NullPtr是可以的,因为它不需要任何事情。

Your Trie::clear() method deletes the same Trie twice.

~Trie() {
    clear(map);
}

void clear(unordered_map<char, Trie*> map) {
    for (auto& pair : map) {
        if (pair.second != nullptr) {
            clear(pair.second->map);
        }
        delete pair.second;
    }
}

The destructor ~Trie calls clear(pair.second->map) and then calls delete pair.second which is the same as clear(pair.second->map) again since delete calls the destructor of the pointed-at data. Calling clear() twice on the same map means that the second call is trying to delete already deleted data, which causes the crash. Calling delete on a pointer does not change the value of the pointer, which is why the nullptr check does nothing.

Since the destructor calls clear(), the clear() method does not need to explicitly call itself recursively. Just delete the map pointers.

~Trie() {
    clear(map);
}

void clear(unordered_map<char, Trie*> map) {
    for (auto& pair : map) {
        delete pair.second;
    }
}

By the way, calling delete nullptr is fine since it is required to do nothing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文