在你的代码中,遍历 QHash
并在特定条件下删除元素可能会导致问题,因为在迭代过程中修改容器的大小是不可取的。你在循环内对哈希表进行了删除操作,但因为使用了迭代器,可能导致行为未定义或迭代器失效。要正确处理,可以采取以下方法之一:
方法一: 使用临时列表记录待删除的键
在遍历 QHash
的时候,将需要删除的键存储在一个临时容器中,遍历完成后再进行删除。这可以避免直接在原容器上进行修改。
QHash<int, st_Studbanswer*>& hash = ConnectClientInfo::GetSocketHash();
QList<int> keysToRemove; // 用于存储待移除的键
for (auto it = hash.constBegin(); it != hash.constEnd(); ++it) {
qDebug() << "Key:" << it.key() << ", Value:" << it.value();
st_Studbanswer* banswerData = it.value();
if (banswerData->HeartbeatStats == 1) {
banswerData->HeartbeatStats = 0;
} else if (banswerData->HeartbeatStats == 0) {
SOCKET sock = static_cast<SOCKET>(it.key());
qDebug() << "SOCKET sock = (SOCKET)(it.key()); ";
if (closesocket(sock) == SOCKET_ERROR) {
qDebug() << "closesocket failed: " << WSAGetLastError() << endl;
} else {
qDebug() << "delete hash.value(it.key());";
delete banswerData; // 释放动态内存
keysToRemove.append(it.key()); // 将键添加到待删除列表
}
}
}
// 从 QHash 中移除所有标记为待删的项
for (int key : keysToRemove) {
hash.remove(key);
}
方法二: 倒序遍历
如果你不想使用临时列表,可以考虑倒序遍历。如果使用整数作为 QHash
的键(如 int 类型),则可以将其转换成 QList 或 QVector 来实现反向遍历。
方法三: 使用 QMutableHashIterator
另一种选择是使用 QMutableHashIterator
,这个迭代器允许你在循环过程中安全地删除项。
QHash<int, st_Studbanswer*>& hash = ConnectClientInfo::GetSocketHash();
QMutableHashIterator<int, st_Studbanswer*> it(hash);
while (it.hasNext()) {
it.next();
qDebug() << "Key:" << it.key() << ", Value:" << it.value();
st_Studbanswer* banswerData = it.value();
if (banswerData->HeartbeatStats == 1) {
banswerData->HeartbeatStats = 0;
} else if (banswerData->HeartbeatStats == 0) {
SOCKET sock = static_cast<SOCKET>(it.key());
qDebug() << "SOCKET sock = (SOCKET)(it.key()); ";
if (closesocket(sock) == SOCKET_ERROR) {
qDebug() << "closesocket failed: " << WSAGetLastError() << endl;
} else {
qDebug() << "delete hash.value(it.key());";
delete banswerData; // 删除指针指向的数据
it.remove(); // 安全地从 QHash 中移除当前项
}
}
}
以上方法都可以避免因直接修改容器而引起的问题,你可以根据自己的需求选择适合的方法来处理。
内容由零声教学AI助手提供,问题来源于学员提问