Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Март 18, 2011, 22:26



Название: Мелкая проблема с ключом-указателем
Отправлено: Igors от Март 18, 2011, 22:26
Добрый вечер

Использую std::map <myPtr *, myData>, т.е. ключ указатель. Это имеет маленький, но противный минус - невоспроизводимость. То есть при новом запуске myPtr могут встать в памяти не так как при предыдущем. Хотя когда я итерирую  контейнер, результат тот же, уходит много времени на отладку - ведь теперь воспроизвести ситуацию не получается. Толкаю - вылетела, еще раз - работает, или наоборот  ;D

Пришлось поместить указатели в вектора а ключи заменить на индексы (в этих векторах). 


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: ufna от Март 18, 2011, 23:49
Добрый вечер

А вопрос сабжа то "кто виноват"? :)


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: serg_hd от Март 19, 2011, 01:32
Человек, видимо, просто делится опытом. Непонятен момент:

То есть при новом запуске myPtr могут встать в памяти не так как при предыдущем.
Что значит "при новом запуске"? Создание объекта в куче? Если да, то выделение будет из другого участка памяти, это же вполне законно. Или в чём подвох? Интересно просто, чтоб не повторить этого.


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Akon от Март 19, 2011, 09:05
Используй hash-контейнер, если такое поведение тебя не устраивает.


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Igors от Март 19, 2011, 12:49
Человек, видимо, просто делится опытом. Непонятен момент:

То есть при новом запуске myPtr могут встать в памяти не так как при предыдущем.
Что значит "при новом запуске"? Создание объекта в куче? Если да, то выделение будет из другого участка памяти, это же вполне законно. Или в чём подвох? Интересно просто, чтоб не повторить этого.
Пример

Код
C++ (Qt)
QMap <MyClass *, int> theMap;  
MyClass * p0 = new MyClass();
theMap[p0] = 0;
...
MyClass * p1 = new MyClass();
theMap[p1] = 1;
...
MyClass * p2 = new MyClass();
theMap[p2] = 2;
...
 
Никто не обещает что p0 < p1 < p2 или что вообще они будут в каком-то фиксированном порядке - зависит от того что с кучей на данный момент. Поэтому напр. theMap.begin() может вернуть итератор на p0 или p1 или p2 (как фишка ляжет) каждый раз когда указатели снова созданы и theMap заполнена. Хотя порядок итерации в большинстве случаев не имеет значения, мне лично это неудобно для ловли багов/отладки.

Используй hash-контейнер, если такое поведение тебя не устраивает.
Насколько мне известно, (Q)hash вообще не обещает что элементы будут итерироваться в каком-то порядке, он просто "arbitrary" (произвольный)


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Akon от Март 19, 2011, 13:22
Да, совершенно верно. Я имел ввиду, что ключ можно вычислять хэш-функцией по данным, а контейнер будет map. В общем, некорректно выразился.

Как вариант с указателями - можешь сделать MyClass::operator new(), который будет использовать твой распределитеть, который будет распределять память строго упорядоченно (p1 < p2 < p3 ...).


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Igors от Март 19, 2011, 13:52
Как вариант с указателями - можешь сделать MyClass::operator new(), который будет использовать твой распределитеть, который будет распределять память строго упорядоченно (p1 < p2 < p3 ...).
Ну это легко для фиксированного (небольшого) числа экземпляров, а иначе я не знаю как. Да и указатель может быть совсем "не на мой класс" и/или лезть в этот класс не резон. В общем, хотя и интересно, но сложновато  :)


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Waryable от Март 19, 2011, 15:35
Так то интересно зачем реализованно именно так. :)
Есть предложение(псевдокод):
Код
C++ (Qt)
struct
{
       int Key;
       TBaseClass* MyClass;
}TStruct;
 
 
QMap<TStruct.key, TStruct>
 


Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Igors от Март 20, 2011, 10:33
Так то интересно зачем реализованно именно так. :)
Есть предложение(псевдокод):
Код
C++ (Qt)
struct
{
       int Key;
       TBaseClass* MyClass;
}TStruct;
 
 
QMap<TStruct.key, TStruct>
 
Какой Вы быстрый  :) Нужно зарядить операторы < и == для TStruct (ну и конструктор для приличия). Плюс Key надо как-то вычислять/наращивать. Я сделал так

Код
C++ (Qt)
typedef size_t TMapID;
QMap <TMapID, MyValue *> theMap;
QVector <MyClass *> theVec;
..
MyClass * p0 = new MyClass();
theMap[theVec.size()] = new MyValue();
theVec.push_back(p0);
 
Это впрочем имеет тот минус что все использующие theMap должны иметь доступ и к theVec.



Название: Re: Мелкая проблема с ключом-указателем
Отправлено: Akon от Март 20, 2011, 21:01
Еще вариант - обертка для MyClass по типу смарт-поинтера, т.е. реализующая operator->() и все необходимое. В обертке есть поле-ключ (например, тупо инкрементальный счетчик). Само-собой, для обертки есть все то, что нужно QMap (operator>() и т.д.). Различия в коде с оберткой и без минимальны.