C++ 如何使用C++/Qt-内存分配有效吗?

C++ 如何使用C++/Qt-内存分配有效吗?,c++,qt,memory,shared-ptr,memory-leaks,C++,Qt,Memory,Shared Ptr,Memory Leaks,我最近开始为自己调查Qt,并有以下问题: 假设我有一些QTreeWidget*widget。在某个时刻,我想向它添加一些项目,这是通过以下调用完成的: QList<QTreeWidgetItem*> items; // Prepare the items QTreeWidgetItem* item1 = new QTreeWidgetItem(...); QTreeWidgetItem* item2 = new QTreeWidgetItem(...); items.append(

我最近开始为自己调查Qt,并有以下问题:

假设我有一些
QTreeWidget*widget
。在某个时刻,我想向它添加一些项目,这是通过以下调用完成的:

QList<QTreeWidgetItem*> items;

// Prepare the items
QTreeWidgetItem* item1 = new QTreeWidgetItem(...);
QTreeWidgetItem* item2 = new QTreeWidgetItem(...);
items.append(item1);
items.append(item2);

widget->addTopLevelItems(items);
但我不知道Qt本身是否会尝试对我的指针进行显式的
delete
调用(这将是灾难性的,因为我将它们声明为
shared\u ptr
-managed)


你将如何解决这个问题?也许一切都很明显,我错过了一些非常简单的东西?

Qt有自己的智能指针,看看。通常情况下,建议尽可能使用Qt的标准所有权层次结构。这一概念如下所述:

对于您的具体示例,这意味着您应该将指向容器(即QTreeWidget)的指针传递给子对象的构造函数。每个QWidget子类构造函数都会为此目的使用一个指向QWidget的指针。当您将子对象指针传递到容器时,容器将接管清理子对象的责任。以下是您需要修改示例的方式:

QTreeWidgetItem* item1 = new QTreeWidgetItem(..., widget);
QTreeWidgetItem* item2 = new QTreeWidgetItem(..., widget);
(我不知道您的示例中的…是什么,但Qt内存管理的重要内容是最后一个参数)

您使用智能指针的示例

shared_ptr<QTreeWidgetItem> ptr(new QTreeWidgetItem(...));
items.append(ptr.get());
shared_ptr ptr(新的QTreeWidgetItem(…);
items.append(ptr.get());

这不是一个好主意,因为您打破了智能指针的黄金法则:永远不要直接使用智能指针管理对象的原始指针。

许多Qt类实例可以使用父QObject*构造。此父对象控制构造的子对象的生存时间。查看QTreeWidgetItem是否可以链接到父窗口小部件,这看起来是这样的,阅读Qt文档:

项目通常由一个 是QTreeWidget的父级 (对于顶级项目)或 QTreeWidgetItem(适用于下方的项目) 树的级别)


快速浏览qtreewidget.cpp可以看到:

void QTreeWidget::clear()
{
   Q_D(QTreeWidget);
   selectionModel()->clear();
   d->treeModel()->clear();
}

void QTreeModel::clear()
{
   SkipSorting skipSorting(this);
   for (int i = 0; i < rootItem->childCount(); ++i) {
       QTreeWidgetItem *item = rootItem->children.at(i);
       item->par = 0;
       item->view = 0;
       delete item;     //   <<----- Aha!
   }
   rootItem->children.clear();
   sortPendingTimer.stop();
   reset();
}
void QTreeWidget::clear()
{
Q_D(QTreeWidget);
selectionModel()->clear();
d->treeModel()->clear();
}
void QTreeModel::clear()
{
SkipSorting SkipSorting(这个);
对于(int i=0;ichildCount();++i){
QTreeWidgetItem*item=rootItem->children.at(i);
项目->标准杆=0;
项目->视图=0;

delete item;//addTopLevelItems()确实会导致QTreeWidgetItems拥有QTreeWidgetItems的所有权。因此,您不应该自己删除它们,或者将它们保存在共享的\u ptr中,否则最终会出现双重删除问题。

M。因此,如果我像您编写的那样将我的子项“绑定”到父小部件,是否可以确保
clear()
例如,调用将处理该内存?是的,您可以。只要您使用Qt的内存管理,Qt就会确保在删除其父对象时删除所有对象(因此Qt严格基于父子内存管理的树进行操作。如果您使用append()或addWidget())或者类似的函数,您不需要在构造函数中明确地设置父函数,尽管这样做不会有什么坏处。
void QTreeWidget::clear()
{
   Q_D(QTreeWidget);
   selectionModel()->clear();
   d->treeModel()->clear();
}

void QTreeModel::clear()
{
   SkipSorting skipSorting(this);
   for (int i = 0; i < rootItem->childCount(); ++i) {
       QTreeWidgetItem *item = rootItem->children.at(i);
       item->par = 0;
       item->view = 0;
       delete item;     //   <<----- Aha!
   }
   rootItem->children.clear();
   sortPendingTimer.stop();
   reset();
}