qt - QLinkedList 中 Qt 迭代器的问题
问题描述
我知道我会被要求提供一个最小的例子,但我不确定是否能想出一个,或者它不会是最小的。但我仍然可以从这次讨论中学到宝贵的知识。
因此,我在 QLinkedList 中组织了一系列给定类的数据项。为用户提供了一个界面,该界面允许浏览该数据并对其进行编辑。特别是,一些可能的编辑操作需要修改 QLinkedList 中的多个条目 - 例如所有后续或所有先前条目。也可以在列表中添加或删除项目,然后进行编辑。
在代码中,我只是让一个迭代器保持最新,它指向链中的当前数据项,称为m_currentItem
. 然后我用它来显示当前项目的数据,从当前循环到结尾或开头。我要求这个迭代器在应用程序的整个执行和生命周期内都有效,即使添加或删除项目也是如此。当用户按下“下一个”或“上一个”时,迭代器只是递增或递减。当用户删除列表中的一个项目(最后一个除外)时,迭代器然后指向下一个条目并显示其内容。当用户在列表中添加一个项目时,m_currentItem
现在会指向这个新项目。
这就是事情出错的地方:在那些向后或向前的循环上。他们经常(但不总是......)超越结束条件并继续进入未知数据,直到发生重大崩溃。有时它还会循环回到列表中的第一个元素(!!!),然后它对你来说是一个无限循环。
这是取自我的代码的示例,有什么明显错误吗?关于 Qt 迭代器还有什么我应该知道的吗?
编辑 :
刚刚了解了反向迭代器!似乎建议使用它们而不是--
标准迭代器上的重载运算符!但是如何制作m_currentItems
反向迭代器?
我还阅读了有关隐式共享的信息......我并没有真正做我不认为的那样的事情,但这是否表明我不应该像我一样使用长寿命的迭代器?
include <QLinkedList>
struct Member
{
int memberID;
}
struct Item
{
/* A map of members, each mapped to an ID */
QMap<int, Member> m_members;
QString name;
}
typedef QLinkedList<Item> LinkedItems;
LinkedItems m_items;
LinkedItems::iterator m_currentItem;
...
if(m_currentItem != m_items.end())
{
for(LinkedItems::iterator iter = m_currentItem+1; iter != m_items.end(); iter++)
{
// Do things on *iter
}
}
一个更复杂的实现:在每个链接的项目中找到包含数据和 ID 的成员。用户可以在所有先前的项目中传播一个 ID,该 ID 位于他被要求选择的项目之前(该项目本身必须位于当前项目之前)。
例如,如果我们有 ABCDEF 并且用户在 E 上,他可以选择将 E 的成员 ID 传播到 C 和以前的项目(所以 A 和 B 也是 - 但不是 D)。
这是代码。大多数或所有迭代器循环都受到意外行为的影响。
void renameAllPreviousMembers(int memberIDToPropagate)
{
/* If first item, then there is no previous altogether */
if(m_currentItem != m_items.begin())
{
if(m_currentItem.m_members.contains(memberIDToPropagate) == false)
{
QMessageBox::critical(nullptr, tr("Rename members in previous items"),
tr("There is no member with the selected ID in the current item."),
QMessageBox::Ok);
return;
}
bool chose_item;
LinkedItems::iterator itemIter;
QStringList previousItems;
QStringList previousItemsBetterOrder;
QMap<QString, LinkedItems::iterator> previousItemsMap;
previousItemsMap.clear();
/* Find all previous items and store them in a QStringList and a map between those strings and actual items */
std::cout << "Search previous items : " << std::flush;
for(itemIter = m_items.begin();
itemIter != m_currentItem;
itemIter++)
{
/* Possibly add conditions on some items that we do not want to apply values to. */
std::cout << itemIter->name << ", " << std::flush;
previousItems << itemIter->name;
previousItemsMap.insert(itemIter->name, itemIter);
}
std::cout << "finished." << std::endl << std::flush;
QStringList::reverse_iterator riter;
for(riter = previousItems.rbegin(); riter != previousItems.rend(); riter++)
{
previousItemsBetterOrder << *riter;
}
QString name_previous_item = QInputDialog::getItem(nullptr,
QString("Previous item"),
QString("Previous item to start from : "),
previousItemsBetterOrder, 0, false, &chose_item);
if(!chose_item)
{
return;
}
/* Decode chosen previous item by retrieving it in the map */
LinkedItems::iterator chosenPrevIter = previousItemsMap.value(name_previous_item);
bool chose_member;
/* Find all existing IDs in previous item */
QStringList previousIDs;
QMap<int, Member>::const_iterator memberIter;
/* Retrieve all members from the chosen previous item */
std::cout << "Search IDs in chosen previous item : " << std::flush;
for(memberIter = chosenPrevIter->m_members.begin(); memberIter != chosenPrevIter->m_members.end(); memberIter++)
{
previousIDs << QString("%1").arg(QString::number(memberIter->ID));
std::cout << memberIter->memberID << ", " << std::flush;
}
std::cout << "finished." << std::endl << std::flush;
/* If no member then no lunch */
if(previousIDs.size() == 0)
{
QMessageBox::critical(nullptr, tr("Rename previous member"),
tr("There are no members in the selected previous item."),
QMessageBox::Ok, QMessageBox::Ok);
return;
std::cout << "Rename previous members finished with no members in chosen previous item." << std::endl << std::flush;
}
QString string_member_id_from_previous = QInputDialog::getItem(nullptr,
QString("Previous member number"),
QString("Member ID from previous item to be used : "),
previousIDs, 0, false, &chose_member);
if(chose_member)
{
int member_id_from_previous = string_member_id_from_previous.toInt();
/* Update member ID at and before chosen previous item */
std::cout << "Update member ID before chosen previous item : " << std::flush;
for(itemIter = chosenPrevIter;
itemIter != m_items.begin();
itemIter--)
{
std::cout << itemIter->name << std::flush;
if(itemIter->m_members.contains(member_id_from_previous))
{
/* Take and reinsert to new ID. */
std::cout << "+" << std::flush;
itemIter->m_members.insert(memberIDToPropagate, itemIter->m_members.take(member_id_from_previous));
}
else
{
/* Do nothing. */
}
std::cout << ", " << std::flush;
}
std::cout << "finished." << std::endl << std::flush;
}
}
else
{
/* Do nothing. */
}
}
else
{
QMessageBox::critical(nullptr, tr("Apply to previous members"),
tr("This is the first item. There are no previous items."),
QMessageBox::Ok);
}
std::cout << "Apply to previous members finished." << std::endl << std::flush;
}
解决方案
推荐阅读
- python - 为什么我不能正确获取访问课程的列表?
- database - AWS DynamoDB 是否适合数据收集和分析应用程序?
- java - 重载 RequestMappings - Java
- c++ - 带 Mergesort 的 DLL 不断崩溃
- php - 在 Woocommerce 中动态更改特定产品的购物车商品价格和名称
- php - phpmailer 和电子邮件垃圾邮件过滤器的问题
- c# - 从对象数组中删除项目
- vue.js - vue js返回空对象响应
- python - Keras:如何在训练期间在自定义生成器中获取模型预测(或最后一层输出)?
- python - 两种类型的标头 txt 到 Pandas 数据框