为什么删除QTreeWidgetItem *会自动推进与同一QTreeWidget关联的迭代器?在我看来的任何地方,此行为似乎都不是IMG。我希望在删除QTreeWidget *之后,迭代器不受影响(除了现在指向无效值)。相反,似乎QTreeWidget析构函数会自动推进QTreeWidget的所有迭代器。
简要介绍qt源代码,我认为这可以通过让所有迭代器在创建模型时向模型注册。然后在documented中调用QTreeItem::~QTreeItem调用QTreeModel::beginRemoveItems()来推进所有迭代器。
除了直接检查所有QT来源外,你怎么知道这种情况发生了?所有QT迭代器都是这样做的吗?我对STL迭代器的经验比对QT的经验更多,也许这就是为什么我发现这是如此意外。
以下代码演示了此行为:
#include <QTreeWidget>
#include <QDebug>
#include <QApplication>
int main(int argc, char **argv)
{
QApplication a( argc, argv );
QTreeWidget * tw_1 = new QTreeWidget();
QTreeWidget * tw_2 = new QTreeWidget();
for(int i = 1; i <=5; i++)
{
tw_1->addTopLevelItem(new QTreeWidgetItem(QStringList(QString("Item %1").arg(i))));
tw_2->addTopLevelItem(new QTreeWidgetItem(QStringList(QString("Item %1").arg(i))));
}
{
qDebug() << "Elements in Tree Widget 1";
QTreeWidgetItemIterator it(tw_1);
while(*it)
{
qDebug() << "\t" << (*it)->text(0);
++it;
}
//Delete the items while iterating over the tree
QTreeWidgetItemIterator ii(tw_1);
while(*ii)
{
delete *ii;
}
qDebug() << "Elements remaining in Tree Widget 1";
QTreeWidgetItemIterator itt(tw_1);
while(*itt)
{
qDebug() << (*itt)->text(0);
++itt;
}
}
{
qDebug() << "Elements in Tree Widget 2";
QTreeWidgetItemIterator it(tw_2);
while(*it)
{
qDebug() << "\t" << (*it)->text(0);
++it;
}
//Delete the items while iterating over the tree
QTreeWidgetItemIterator ii(tw_2);
while(*ii)
{
delete *ii;
++ii;
}
qDebug() << "Elements remaining in Tree Widget 2";
QTreeWidgetItemIterator itt(tw_2);
while(*itt)
{
qDebug() << (*itt)->text(0);
++itt;
}
}
}
这会产生输出:
Elements in Tree Widget 1
"Item 1"
"Item 2"
"Item 3"
"Item 4"
"Item 5"
Elements remaining in Tree Widget 1
Elements in Tree Widget 2
"Item 1"
"Item 2"
"Item 3"
"Item 4"
"Item 5"
Elements remaining in Tree Widget 2
"Item 2"
"Item 4"
答案 0 :(得分:0)
迭代器在QList
中定义为QTreeModel
。
QList
是基于索引的。如果删除了具有当前索引的项目,则下一个项目将成为当前索引。
请参阅以下链接。您将看到迭代器的定义,如下所示。
https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qtreewidget_p.h.html#QTreeModel
你会看到像这样的定义
QList<QTreeWidgetItemIterator*> iterators;
现在,当你在迭代器上调用delete时,会调用QTreeWidgetItemIterator
的析构函数。
QTreeWidgetItemIterator::~QTreeWidgetItemIterator()
{
d_func()->m_model->iterators.removeAll(this);
}
通过注意上面的代码,使用QList
函数removeAll
删除迭代器,并从列表中完全删除迭代器。
QList
是基于索引的。因此,如果删除了具有索引3的迭代器,则下一个迭代器索引将变为3。
现在当你做++时,
下面的函数被调用,它会带来列表中的下一个项目。所以你将迭代器移到下一个项目(索引4)。
QTreeWidgetItemIterator &QTreeWidgetItemIterator::operator++()
{
if (current)
do {
current = d_func()->next(current);
} while (current && !matchesFlags(current));
return *this;
}
模型的 QTreeWidgetItemIterator
维护为QList
。因此,当您删除迭代器时,下一个迭代器将成为当前索引。所以你确实注意到了这种行为。