0

我是 C++ 新手,我正面临着std::cout我不理解的奇怪行为。特别是,当我想打印第二个节点的值时,使用cout << nd.next[2]->next[17]->val,我得到了一些令人费解的字节。但是,如果我先将其设置为变量,例如string let2 = nd.next[2]->next[17]->val,然后使用cout << let2,它会打印正确的字符。我的代码在下面,我正在实现一个 trie。(此外,由于我对 c++ 非常陌生,因此感谢您对我在代码中做错的任何其他评论)

#include <iostream>
#include <set>
#include <iterator>
#include <map>
#include <string>
#include <unordered_map>

using std::set;
using std::cout;
using std::endl;
using std::string;

struct Node {
    Node* next[26]; 
    string val; 

    void insert(string str) {
        cout << "insert " << str << endl;
        insert(str, 0);
    }

    void insert(string str, int idx) {
        if (idx >= str.length()) {
            return;
        }

        char cur = str[idx];
        int curIdx = cur - 'a';
        cout << "cur: " << cur << endl;
        cout << "cur idx: " << curIdx << endl;
        if (!next[curIdx]) {
            Node newNode = Node();
            newNode.val = cur;
            next[curIdx] = &newNode;
        }

        next[curIdx]->insert(str, idx+1);
    }
};

int plus(int a, int b) {
    return a+b;
}
int main() {

    Node nd = Node();
    nd.insert("cryptography");
    string let1 = nd.next[2]->val;
    string let2 = nd.next[2]->next[17]->val;
    cout << "first letter " << let1 << endl; // c
    cout << "second letter " << nd.next[2]->next[17]->val << endl; // wrong
    cout << "second letter " << let2 << endl; // work as expected
    cout << "sum " << plus(1,2) << endl; // work as expected
    // cout << nd.next[2]->next[17]->val << endl;

    return 0;
}
4

1 回答 1

0

关于您问题的第二部分(“我做错了什么”),在您在堆栈上insert()创建对象并分配指向该对象的指针的方法中。但是,一旦执行超出定义该对象的范围,该堆栈对象就会自动销毁,因此最终指向垃圾(对象在销毁之前所在的内存)。 不确定下一行是如何工作的,此时指向垃圾:Node()next[curIdx]next[curIdx]
next[curIdx]next[curIdx]->insert(str, idx+1);

相反,您应该使用运算符在堆上分配 Node 对象new,例如:

        if (!next[curIdx]) {
            next[curIdx] = new Node();  // allocated on heap
            next[curIdx]->val = cur;
        }

但是你应该确保delete在某个时候释放()它们以避免内存泄漏。Node 的析构函数可能是一个很好的地方——您可以递归地delete从下一个数组中递归所有非空节点。

您也可以使用智能指针而不是原始指针,它们会在无法再访问时自动删除对象(垃圾收集器在 Java 和 C# 等其他语言中自动执行此操作)。

有关堆栈与堆的更多信息:https ://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

于 2019-12-12T17:44:03.013 回答