我已经开始使用 trie 实现字典了。基本上,我有一个根节点,它有一个定义(指向T
的指针,表示与键相关的de值)和childs(指向包含指向256个节点的指针的数组的指针,每个字母一个)。检查定义:
template<typename T>
class DiccString {
public:
DiccString() : root(NULL);
DiccString(const DiccString<T>&);
~DiccString() {delete root;}
void define(const string& key, const T& value);
bool isDefined(const string& key) const;
const T& getDefinition(const string& key) const;
T& getDefinition(const string& key);
void remove(const string& key);
const Set<string>& keys() const;
private:
struct Node{
Node** childs;
T* definition;
Node(){
std::cout << "Node has been created " << this << std::endl;
childs = new Node*[256];
definition = NULL;
}
~Node(){
std::cout << "Node has been deleted " << this << std::endl;
delete definition;
delete [] childs;
}
};
Node* root;
};
所以,如果我想存储&#34; John &#34;值 14 (T
将是int
所以),假设没有其他密钥,那么我将创建一个根,然后在root-&gt; {{1我将创建另一个节点&#34; nodeJ&#34;,然后是nodeJ-&gt; childs[(int)'j']
,依此类推,直到到达最后一个节点&#34; nodeN&#34;,它将包含该值(childs[(int)'o']
)。
问题出在我做的时候:
nodeN->definition = 14
然后我希望所有创建的节点都被销毁,但看一下输出:
int main() {
DiccString<int> d;
d.define("john",20);
d.define("jane",25);
return 0;
}
正在删除根目录。显然,当在Node created 0x61fc20 // root
Node created 0x620860 // for letter 'j'
Node created 0x621090 // for letter 'o' (child of 'j' 0x620860)
Node created 0x6218c0 // for letter 'h' (child of 'o' 0x621090)
Node created 0x6220f0 // for letter 'n' (child of 'h' 0x6218c0), value: 20
Node created 0x622990 // for letter 'a' (child of 'j' 0x620860)
Node created 0x6231c0 // for letter 'n' (child of 'a' 0x622990)
Node created 0x6239f0 // for letter 'e' (child of 'n' 0x6231c0), value: 25
Node deleted 0x61fc20 // root
的析构函数中执行delete [] childs
时,它并没有删除数组的所有元素,我确信它们存在:例如,在调用root的析构函数(实际上是唯一被调用的函数)的情况下,我评估了Node
,它肯定是0x620860,所以我知道它应该调用这个元素的析构函数(at至少)当它执行childs[(int)'j']
时,对吧?
我做错了什么?
答案 0 :(得分:2)
childs
的类型为Node**
,它是指向指针的指针。你为它分配了一个Node*
指针数组。
delete[] childs
删除此分配,即仅删除指针的内存,而不删除指针指向的对象。
我们没有看到您实际分配Node
的代码,但是您必须以某种方式存储256个分配的Node*
中的哪一个实际指向有效的Node
对象。也许你通过用NULL指针标记指针来做到这一点?在这种情况下,您可能希望执行以下操作:
for(int i=0; i<256; ++i) {
delete childs[i];
}
我还应该注意,如果Node指针的数量是固定的,你应该使用静态数组,否则你应该使用std::vector
。
答案 1 :(得分:0)
打印输出仅用于销毁Node
个对象而不是Node *
。您可以使用调试器检查行为是否正确。
请注意,如果您在构造函数/析构函数中具有对称性,则可能更清楚,而不是在define()
中进行延迟分配。当释放DiccString
时,请务必正确处理error: Name clash for '<pstage/lib>libboost_atomic.so.1.62.0'
error:
error: Tried to build the target twice, with property sets having
error: these incompatible properties:
error:
error: - <debug-symbols>on <inlining>off <optimization>off <runtime-debugging>on <variant>debug
error: - <debug-symbols>off <define>NDEBUG <inlining>full <optimization>speed <runtime-debugging>off <variant>release
error:
error: Please make sure to have consistent requirements for these
error: properties everywhere in your project, especially for install
error: targets.
为空的情况。