Russian Qt Forum
Ноябрь 22, 2024, 22:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: кэширование объектов (не web). [РЕШЕНО]  (Прочитано 5514 раз)
spirits25
Гость
« : Апрель 19, 2013, 11:26 »

Всем привет!

Столкнулся с простой задачей, но не знаю как лучше и правильнее её реализовать.
Допустим есть города, улицы, дома. Для них есть city_id, street_id, builder_number - все целочисленные и с помощью всех трёх значений можно точно идентифицировать объект здания. Допустим, дом - это 3d модель, которая строится по каким-то данным, то есть строить каждый раз накладно.

И вот мы сохраняем N (например, последних) зданий в памяти. У нас должны быть ключи (city_id, street_id, builder_number), чтобы проверить и взять(если есть) объект из памяти, что-то вроде myHash[15][32][87].
Как лучше организовать этот "словарь"? Использовать вложенные QHash или QMap? Или есть красивые и простые способы для этого?
« Последнее редактирование: Апрель 22, 2013, 11:46 от spirits25 » Записан
mutineer
Гость
« Ответ #1 : Апрель 19, 2013, 11:30 »

Если перебирать подряд не надо, а надо только получать доступ по конкретной тройке, то я бы советовал QHash с ключем-струтурой из трех значений
Записан
spirits25
Гость
« Ответ #2 : Апрель 19, 2013, 11:38 »

Если перебирать подряд не надо, а надо только получать доступ по конкретной тройке, то я бы советовал QHash с ключем-струтурой из трех значений

Спасибо, о структуре я что-то не подумал. Да, мне "надо только получать доступ по конкретной тройке"=)

Не совсем по теме, порадовала оптимизация всего этого в Qt5 http://habrahabr.ru/post/170017/
Записан
spirits25
Гость
« Ответ #3 : Апрель 19, 2013, 13:55 »

Если перебирать подряд не надо, а надо только получать доступ по конкретной тройке, то я бы советовал QHash с ключем-струтурой из трех значений

Что-то не совсем у меня получается. На методе insert показывает ошибку.
Нашёл такую строчку в доках
Цитировать
The key type of a QHash must provide operator==() and a global hash function called qHash() (see qHash).
Может со структурой не прокатит? Или можете привести пример рабочего кода?
Записан
spirits25
Гость
« Ответ #4 : Апрель 19, 2013, 14:05 »

Попробовал добавить что-то вроде
Код:
    
bool operator==(const MyStructType& n)
    {
        if(n.a != a || n.b!= b || n.c != c)
            return false;
        return true;
    }

Но всё равно ошибка.
Цитировать
ошибка: no matching function for call to 'qHash(const MyStructType&)'

Как я понял, нужно не только добавить operator==, но и перегрузить QHash()?

~~~~~~~~~~~~~~~~~

Далее сделал так, но безуспешно:
Код:
struct MyStructType{
    qint32 x;
    qint32 y;
    qint32 z;
    bool operator==(const MyStructType &key)
    {
        if(key.x != x || key.y!= y || key.z != z)
            return false;
        return true;
    }
};

inline uint qHash(const MyStructType &key)
{
    return qHash( key.x ) ^ qHash( key.y ) ^ qHash( key.z );
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QHash<MyStructType, QString> tileNodeCache;

    MyStructType myStruct;
    myStruct.x = 1;
    myStruct.y = 2;
    myStruct.z = 3;

    tileNodeCache.insert(myStruct, "test");
    tileNodeCache[myStruct] = "test";

    return a.exec();
}

не работает, ни "tileNodeCache.insert(myStruct, "test");" , ни "tileNodeCache[myStruct] = "test";".

~~~~~~~~~~~~~~~~~~~~~~~~

Единственное решение, которое нашёл - http://stackoverflow.com/questions/13337896/qt4-qhash-hash-collision
« Последнее редактирование: Апрель 19, 2013, 15:31 от spirits25 » Записан
mutineer
Гость
« Ответ #5 : Апрель 19, 2013, 16:09 »

"не работает" - в смысле не добавляет? и ошибки не пишет никакие?
« Последнее редактирование: Апрель 19, 2013, 16:14 от mutineer » Записан
spirits25
Гость
« Ответ #6 : Апрель 19, 2013, 16:16 »

"не работает" - в смысле не добавляет? и ошибки не пишет никакие?

вот так всё отлично=)

Код:
class NewHashClass
{
public:
    NewHashClass(const int value1,const int value2,const int value3):
      value1(value1),
      value2(value2),
      value3(value2)
    {}

    int getValue() const
    {
        return qHash(value1) ^ qHash( value2 ) ^ qHash( value3 );
    }

//private:
    int value1;
    int value2;
    int value3;
};

bool operator==(const NewHashClass &b1, const NewHashClass &b2)
{
    return (b1.value1 == b2.value1 && b1.value2 == b2.value2 && b1.value3 == b2.value3);
}

uint qHash(const NewHashClass &key)
{
    return qHash(key.value1) ^ qHash( key.value2 ) ^ qHash( key.value3 );
}
Записан
Syveren
Гость
« Ответ #7 : Апрель 22, 2013, 11:10 »

Если место в словаре ограничено, то есть удобный класс QCache.
При заполнении, удалит элемент, к которму было менее всего обращений.
Записан
spirits25
Гость
« Ответ #8 : Апрель 22, 2013, 11:23 »

Если место в словаре ограничено, то есть удобный класс QCache.
При заполнении, удалит элемент, к которму было менее всего обращений.

Это вместо QHash использовать? Он умеет правильно удалить объект помещённый в него?

По QHash очень мало документации и я не пойму как перегрузить его для произвольного ключа..
« Последнее редактирование: Апрель 22, 2013, 11:33 от spirits25 » Записан
mutineer
Гость
« Ответ #9 : Апрель 22, 2013, 11:40 »

По QHash очень мало документации и я не пойму как перегрузить его для произвольного ключа..

Ты же вверху написал что работает уже
Записан
spirits25
Гость
« Ответ #10 : Апрель 22, 2013, 11:45 »


Ты же вверху написал что работает уже

Я описался, про QCache хотел написать=) Хотя разобрался, там даже что-то вроде переопределения qHash метода (как для QHash) делать не надо, в QCache указываются ключ и значение просто, не как указатели, а значение необходимо передавать как указатель. Меня это смутило. В общем и QHash и QCache работают, но юзать скорее буду QCache=)

Всем большое спасибо!=)
Записан
romanster
Гость
« Ответ #11 : Июль 18, 2013, 13:35 »

Здравствуйте элементарщина не получается если можно подскажите пожалуйста. Объявил класс :
class HashClass
{
public:
    HashClass(QString value1, QString value2,  QString value3);

      QString value1() const;
      QString value2() const;
      QString value3() const;

private:
  QString vvalue1, vvalue2, vvalue3;
};

inline bool operator==(const HashClass &a, const HashClass &b)
{
    return (a.value1() == b.value1()) && (a.value2() == b.value2()) && (a.value3() == b.value3());
}

inline uint qHash(const HashClass &key)
{
    return qHash(key.value1()) ^ qHash( key.value2() ) ^ qHash( key.value3() );
}

HashClass::HashClass( QString value1, QString value2, QString value3 ) : vvalue1( value1 ),vvalue2( value2 ),vvalue3( value3 ){}
QString HashClass::value1() const { return vvalue1;}
QString HashClass::value2() const { return vvalue2;}
QString HashClass::value3() const {return vvalue3;}

Для кнопки описал процедурку подконнектил и пытаюсь что то записать в хэш и извлеч от туда:
void window::Generate(){
    QHash<HashClass,int> hash;
    hash[HashClass("1", "2","3")] = 10;


    QString s = "";
    int n = hash.count(HashClass("1", "2","3"));

    QMessageBox::information(this, tr("inf"), s.number(n, 10));
}

Выдает оч много ошибок и не компилируется не указывает что именно в листинге не так.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.081 секунд. Запросов: 21.