VirtualTreeView在C ++ Builder中为UnicodeString完成

我在C ++ Builder中使用了VirtualTreeView,并将其用于这样的结构:

struct TVTNodeData
   {
   int Index;
   UnicodeString Caption;
   }

我使用循环预先填充树的节点:

TVirtualNode *Node = VTree->AddChild(NULL);
pNode = (TVTNodeData *)VTree->GetNodeData(Node);
pNode->Index = 1;
pNode->Caption = "Whatever";

我发现应用程序的内存不断增加(内存泄漏),即使我清除树并重新加载它。 此页面 - http://www.remkoweijnen.nl/blog/2010/06/09/memory-leaks-when-using-virtual-treeview-component/建议在OnFreeNode事件中执行Finalize()。 目前很好。

但是在C ++中没有Finalize()。 我在OnFreeNode事件中尝试了pNode->Caption="" ,并且内存不再被大幅分配,但仍然有点OnFreeNode 。 我认为即使它被清空(引用计数> 0),也可能引用UnicodeString左侧。

如何在C ++中为UnicodeString释放OnFreeNode事件中的节点数据? 我知道UnicodeString是分配的,直到所有引用计数为零 - 那么我如何强制引用计数变为零?

另外,如果节点在OnNodeInit分配 - OnFreeNode事件中是否也适用?

如果TVTNodeData结构纯粹是虚拟的 - 该节点永远不可见,也不使用AddChild或OnNodeInit进行初始化,然后需要Finalize,结构是否存在于内存中呢?

更新:我后来发现我正在测量内存使用不正确,并且将字符串设置为空字符串对清除内存数据来说足够了。 但是 - 正如Rob Kennedy在他的回答中所建议的那样,调用struct〜析构函数甚至更好,等同于Finalize,并且更容易,因为它清除了整个结构(如果其中有更多字符串)。


Delphi的Finalize具有释放记录中任何编译器管理的类型的效果。 在C ++中,这通常是类型析构函数的工作。 在你的OnFreeNode事件处理程序中,直接调用你的数据类型的析构函数:

TVTNodeData* const pNode = static_cast<TVTNodeData*>(Sender->GetNodeData(Node));
pNode->~TVTNodeData();

这将调用UnicodeString对象的析构函数,它将释放关联的字符数据。 当树控件为节点分配TVTNodeData ,它与TVirtualNode对象本身位于同一块内存中,因此您不能只调用delete

树控件使用全零位初始化数据。 如果你的数据中有一个对象不是正确的初始化(形式上正确,包括所有非POD类型),那么你应该在OnInitNode事件中调用你的数据的构造函数。 使用放置新功能来完成此操作。 例如:

TVTNodeData* const pNode = static_cast<TVTNodeData*>(Sender->GetNodeData(Node));
new (pNode) TVTNodeData();

这将调用TVTNodeData成员的构造函数,而不为另外的TVTNodeData实例分配内存。

如果一个节点从未初始化,那么它也不会被最终确定。 OnInitNode事件永远不会运行,所以树会知道节点没有被初始化。 未初始化的节点没有完成,所以你没有什么可担心的。


我认为并不是所有的节点都经过验证,可能是因为它们没有被显示。 尝试在AddChild后调用ValidateNode。

链接地址: http://www.djcxy.com/p/5969.html

上一篇: VirtualTreeView Finalize in C++ Builder for UnicodeString

下一篇: How to structure database for quick node access