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