Я использую Qt 4.7.4 с MS Visual C ++ 2010.
Я использую следующий QMap:
QMap<T_FileMapKey, HANDLE> m_oMapHistHandle;
где T_FileMapKey определяется как:
typedef struct tagT_FileMapKey
{
int iSubscriptIdx;
int iFilterIdx_1;
int iFilterIdx_2;
} T_FileMapKey;
Чтобы все это заработало, я перегрузил < оператор:
bool operator< (const T_FileMapKey& tVal1, const T_FileMapKey& tVal2)
{
if(tVal1.iSubscriptIdx < tVal2.iSubscriptIdx)
{
return true;
}
else
{
if(tVal1.iFilterIdx_1 < tVal2.iFilterIdx_1)
{
return true;
}
else
{
if (tVal1.iFilterIdx_2 < tVal2.iFilterIdx_2)
{
return true;
}
else
{
return false;
}
}
}
};
Как вы могли предположить, вся эта операция заключается в хранении файловых дескрипторов в трехмерном массиве, как в порядке. Я использую QMap, так как используется только несколько комбинаций индексов, и они могут быть большими числами.
Моя проблема:
if (INVALID_HANDLE_VALUE == m_oMapCurrHandle.value(tFileKey, fdInvalidHandle))
....
а также
if (false == m_oMapHistHandle.contains(tFileKey))
....
(где tFileKey — переменная T_FileMapKey) не всегда возвращает правильное значение.
При нормальных обстоятельствах QMap растет с течением времени, а это означает, что при обнаружении новой комбинации индексов открывается файл и запись добавляется в QMap.
Если я запускаю приложение в режиме отладки, надстройка Qt Visual Studio позволяет мне просматривать сохраненные пары ключ-значение. Я вижу, что запись в Watch отладки присутствует (например, {0, 32767, 0}), но два вызова функций (содержат и значение) говорят мне, что в QMap такой ключ не хранится.
Обычно такое поведение встречается после того, как QMap имеет по крайней мере 15 пар ключ-значение.
Может ли это быть ошибкой в Qt 4.7.4? Что я делаю не так?
Ваш operator<
неправильно. Чтобы объяснить, давайте рассмотрим более простую причину для написания operator<
Просто для pair<int, int>
, Ваша версия реализована таким образом:
bool operator<(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
if (lhs.first < rhs.first) {
return true; // (1)
}
else if (lhs.second < rhs.second) {
return true; // (2)
}
else {
return false; // (3)
}
}
Так {1,4}
< {2,3}
из-за (1). Но {2,3}
< {1,4}
из-за (2)! Таким образом, мы в конечном итоге с operator<
это не устанавливает порядок.
Самый простой способ установить лексикографическое сравнение — полностью разобраться с каждым термином по очереди:
bool operator<(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
if (lhs.first != rhs.first) {
return lhs.first < rhs.first;
}
else {
return lhs.second < rhs.second;
}
}
Эта же идея может быть легко распространена на вашу тройку.
Я думаю, что ваша проблема в вашем меньшем операторе, потому что вы никогда не сравнитесь с большим знаком.
У вас должно быть что-то подобное:
bool operator< (const T_FileMapKey& tVal1, const T_FileMapKey& tVal2)
{
if(tVal1.iSubscriptIdx < tVal2.iSubscriptIdx)
{
return true;
}
else if (tVal2.iSubscriptIdx < tVal1.iSubscriptIdx)
{
return false ;
}
else
{
if(tVal1.iFilterIdx_1 < tVal2.iFilterIdx_1)
{
return true;
}
else if (tVal2.iFilterIdx_1 < tVal1.iFilterIdx_1 )
{
return false ;
}
else
{
if (tVal1.iFilterIdx_2 < tVal2.iFilterIdx_2)
{
return true;
}
else
{
return false;
}
}
}
};
Я использовал только меньше оператора, потому что вы можете не иметь других определенных