Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Классы hashtable, idictionary и другие для Win32


Автор: Killerman 23.6.2009, 09:18
Кто знает, какие классы из STL или может каких то других библиотек есть для Win32 вместо .NET-ских Hastable, Dictionary и т.д.
классы map<> и set<> из STL не устраивают. И немного напрягает работа с итераторами. То, что для .NET-ских классов выглядит как простой вызов функции, для STL классов превращается в длинную писанину.


Автор: jonie 23.6.2009, 09:31
STL для Win32 ?! это что-то новенькое.
http://www.cplusplus.com/reference/stl/
вот перечень контейнеров

Автор: Rififi 23.6.2009, 09:37
Killerman, 
какие классы из STL
без итераторов - никакие.

классы map<> и set<> из STL не устраивают.
тогда делать свои поделки

Автор: jonie 23.6.2009, 10:05
дак и в .net тоже итераторы есть (IEnumerable или IEnumerable<T> почти наследуются все коллекции тамошние)...

Автор: Rififi 23.6.2009, 10:15
jonie, 
дак и в .net тоже итераторы есть 
т-с-с-с! а то спугнёшь smile

Автор: Killerman 23.6.2009, 10:27
jonie, 
дак и в .net тоже итераторы есть 

Есть, но их не нужно использовать явно. А класс hashtable я вообще не нашел для Win32.

Я просто подумал. может есть какая то дополнительная библиотека независимых разработчиков....

Автор: W4FhLF 23.6.2009, 10:46
Killerman, а чем конкретно стандартные map и set не устраивают?


Цитата(Killerman @  23.6.2009,  10:27 Найти цитируемый пост)
А класс hashtable я вообще не нашел для Win32.


boost::intrusive::hashtable

Цитата(Killerman @  23.6.2009,  10:27 Найти цитируемый пост)
Я просто подумал. может есть какая то дополнительная библиотека независимых разработчиков....


Boost.Intrusive

Автор: Lazin 23.6.2009, 10:58
Цитата(Killerman @  23.6.2009,  10:27 Найти цитируемый пост)
Есть, но их не нужно использовать явно

используй boost foreach, либо алгоритмы

Код

std::vector<int> values;

...

BOOST_FOREACH( int x , values )
{
    std::cout << x << std::endl;
}

...

struct print_int
{
void operator () (int i) { std::cout << i << std::endl; }
};

std::for_each(values.begin(), values.end(), print_int());

....

std::copy(values.begin(), values.end(), std::ostream_iterator<int>(std::cout));

Автор: Killerman 23.6.2009, 11:25
W4FhLF
Killerman, а чем конкретно стандартные map и set не устраивают?

Ну тем, что все оно какое то роботское.
К примеру в map нельзя проверить, что елемент какой то не существует через:

map<int, char,ltd::less<int>> m1;

if(map[10] ==NULL) //error 

Через map[10] можно только изменить значение, но не вывести результат.
Получается мне нужно сначала создать итератор:
Код

map<int, char,ltd::less<int>>::const_iterotor iter1;

// потом произвести поиск

result = false;
for(iter = m1.begin(), iter!=m1.end(); ++ iter)
{
    if(iter->first ==10)
  {
        result = true;
        break;
    }

}

if(result == fasle)
{
  .............
}


Ну короче ясно о чем я.

Или еще такой прикол, к примеру мне нужно динамически создать список, ну вот так:

std::deque<int> * s1 = new std::deque<int>;

поработать с нима, потом обратиться к элементу 10-ть этого списка.
Для этого приходится делать так:

(*s1)[10]; //выглядит не очень читабельно.

Все усложняется, когда эти конструкции более вложенные:

Бывает и такое:
(*list1[i])[j];
 
и такое:

nd->SetAtributes("F1", new BitArray(*((BitArray*)nd->Childs()[0]->GetAtributes("F1"))));


И иногда вспоминаешь С#, где просто обращаешся через всю иерархию классов через простую точку:
с1.с2[i].c3.c4..................



А де этот boost скачать?

Автор: W4FhLF 23.6.2009, 11:38
Цитата(Killerman @  23.6.2009,  11:25 Найти цитируемый пост)
Ну тем, что все оно какое то роботское.К примеру в map нельзя проверить, что елемент какой то не существует через:
map<int, char,ltd::less<int>> m1;if(map[10] ==NULL) //error 
Через map[10] можно только изменить значение, но не вывести результат.Получается мне нужно сначала создать итератор:


Код

    typedef std::map<int, std::string> StringTable;
    StringTable stable;

    stable[10] = "Ten";

    //StringTable::const_iterator it = stable.find(10);
    if(stable.find(10) != stable.end())
        std::cout << stable[10] << std::endl;


Добавлено через 1 минуту и 27 секунд
Цитата(Killerman @  23.6.2009,  11:25 Найти цитируемый пост)
(*s1)[10]; //выглядит не очень читабельно.


Код

s1->at(10);


Добавлено через 2 минуты и 37 секунд
Цитата(Killerman @  23.6.2009,  11:25 Найти цитируемый пост)
и такое:nd->SetAtributes("F1", new BitArray(*((BitArray*)nd->Childs()[0]->GetAtributes("F1"))));И иногда вспоминаешь С#, где просто обращаешся через всю иерархию классов через простую точку:с1.с2[i].c3.c4..................


А такие конструкции, как правило, связаны с ошибками архитектуры и проектирования. 

Автор: Killerman 23.6.2009, 12:22
C ->at(10) это да. Немного удобнее. Но по поводу архитектуры не согласен.
Просто если конструкция не очень сложная, то все рабоает неплохо. 
А когда задача усложняется, то Win32 начинает очень заметно проигрывать Net-у в читабельности и быстроте написания. Особенно заметно это для объектов с динамически-выделяемой памятью.

Автор: xvr 23.6.2009, 12:30
Цитата(Killerman @ 23.6.2009,  12:22)
Просто если конструкция не очень сложная, то все рабоает неплохо. 

Оно и для сложных неплохо работает
Цитата

А когда задача усложняется, то Win32 начинает очень заметно проигрывать Net-у в читабельности и быстроте написания. 
А не надо на С++ писать как на С# - это разные языки, и подходы к проектированию программ на них тоже разные
Цитата

Особенно заметно это для объектов с динамически-выделяемой памятью.
А вот этого (динамической памяти) в С++ (по сравнению с C#) должно быть гораздо меньше
Тогда будет все нормально

Автор: azesmcar 23.6.2009, 12:56
Killerman

Перечитал все, так и не понял в чем проблема? Чем тебе не нравится STL? Не нравится интерфейс, стиль или названия функций, пиши свой адаптер. Хотя неправильно это. Я бы на твоем месте послушал этого совета
Цитата(xvr @  23.6.2009,  12:30 Найти цитируемый пост)
не надо на С++ писать как на С# - это разные языки, и подходы к проектированию программ на них тоже разные


Автор: Killerman 23.6.2009, 13:55
xvr
А вот этого (динамической памяти) в С++ (по сравнению с C#) должно быть гораздо меньше
Тогда будет все нормально

azesmcar 
Перечитал все, так и не понял в чем проблема? Чем тебе не нравится STL? 

Ну я в принципе согласен, что динамической памяти надо бы по меньше.
Но мне кажется это самообман. Ведь даже те же списки последовательностей (list, vector, deque, ) а также map, set.... - это ни что иное, как динамическая память.

У меня задача такая, использовать map map-ов, или map vector-ов, или vector vector-ов. Получается, я не могу динамически не выделять 2-й компонент, как к примеру:

map<int,map<int,string>> mapofmap;

Конечно можно было бы оставить так, но в таком случае при добавлении нового элемента в mapofmap все данные должны копироваться из вложенного map-а:

map<int,string> m1;
m1.insert(5, "ssss"); // так нельзя, но мне лень расписывать
mapofmap.insert(7, m1); // НЕЯВНО выделяется динамическая память в mapofmap и идет копирование из m1 в элемент mapofmap

Поэтому я использую map<int,map<int,string>*> mapofmap;

Тогда получается ЯВНАЯ динамическая память.
map<int,string>* m1 = new map<int,string>;
mapofmap.insert(7, m1); // копируется только указатель.

К тому же последний вариант иногда более предпочтителен, чтобы не множить одни и те же данные.

Если можно сделать проще, скажите как.




Автор: azesmcar 23.6.2009, 14:01
Цитата(Killerman @  23.6.2009,  13:55 Найти цитируемый пост)
У меня задача такая, использовать map map-ов, или map vector-ов, или vector vector-ов. Получается, я не могу динамически не выделять 2-й компонент, как к примеру:

можешь, 
Код

typedef std::map<int, std::map<int, int> > mmap;
mmap m;
m.insert( mmap::value_type(10, std::map<int, int>()) );

но я что-то плохо себе представляю ситуацию в которой такое может понадобиться.

Добавлено через 1 минуту и 7 секунд
Цитата(Killerman @  23.6.2009,  13:55 Найти цитируемый пост)
Ну я в принципе согласен, что динамической памяти надо бы по меньше.

т.е. ты имеешь ввиду - чем больше динамически выделяемой памяти - тем хуже?
Я ты попробуй несколько мегабайт в стеке выделить - тогда поговорим. smile 

и что значит
Цитата(Killerman @  23.6.2009,  13:55 Найти цитируемый пост)
ЯВНАЯ динамическая память

?

Автор: Lazin 23.6.2009, 14:15
ты что, и на шарпе так пишешь? 
твой map map-ов и map vector-ов должны что-то означать, к примеру vector содержит список жильцов дома, а map - список домов, по их номерам, ну так кто тогда мешает написать

Код

struct House
{
    std::vector<std::string> owners;

    typedef std::vector<std::string>::iterator iterator;

    void add_owner(std::string name) { owners.push_back(name); }   
    ....
};

struct City
{
    std::map<int/*house number*/, House*> houses;

    void add_owner(int number, std::string name) 
   { 
        assert(house_exists(number));
        houses[number]->add_owner(name);
    }

    bool house_exists(int num) { return houses.find(num) != houses.end(); }
    ....
};

City bobruysk;
...
if (bobruysk.house_exists(3))
    bobruysk.add_owner(3, "Vasya");



вместо того, что-бы городить такое: std::map< int, std::vector<std::string> >...
и на шарпе это будет выглядеть не менее ужасно - Dictionary<int, List<String>> city;

Автор: Killerman 23.6.2009, 14:50
azesmcar 
Цитата

typedef std::map<int, std::map<int, int> > mmap;
mmap m;
m.insert( mmap::value_type(10, std::map<int, int>()) );


ну так я ж об этом написал. Но динамическая память всеравно выделятеся в mmap m, только она скрыта в реализации mmap (НЕЯНАЯ для пользователя).

А ЯВНАЯ, это когда открыто создаешь объект через new.


ну вектор векторов и меп мепов, или еще хуже мем мепов векторов часто нужно в задачах, к примеру синтаксического анализа, динамического построения таблиц, разпознавания и т.д.
Короче нада мне  smile 

А по поводу динамической памяти - я как раз за. Только вот сложно с ней в приложениях для win32.

Если б как то увязать win32 обрабоку оконных месседжей и NET классы. Но это похоже нереально.



Автор: azesmcar 23.6.2009, 14:54
Цитата(Killerman @  23.6.2009,  14:50 Найти цитируемый пост)
Короче нада мне  smile 

А мне надо миллион долларов и билет до Хельсинки.

Цитата(Killerman @  23.6.2009,  14:50 Найти цитируемый пост)
Если б как то увязать win32 обрабоку оконных месседжей и NET классы. Но это похоже нереально.

Пиши на C# unmanaged code.

Автор: Killerman 23.6.2009, 15:15
Lazin
Цитата

вместо того, что-бы городить такое: std::map< int, std::vector<std::string> >...
и на шарпе это будет выглядеть не менее ужасно - Dictionary<int, List<String>> city;


На шарпе оно токо в объявлении ужасно. А при работе потом очень даже.

Цитата

к примеру vector содержит список жильцов дома, а map - список домов, по их номерам, ну так кто тогда мешает написать


Ну оно то да, но только красивая обертка. И классы создавать новые. Хотя. может.

azesmcar 
Цитата

Пиши на C# unmanaged code. 

 smile  интересно. не слышал. Може оно еще генерит асм код напрямую??

Автор: azesmcar 23.6.2009, 15:17
Цитата(Killerman @  23.6.2009,  15:15 Найти цитируемый пост)
 smile  интересно. не слышал. Може оно еще генерит асм код напрямую?? 

http://www.codeproject.com/KB/cs/unmanage.aspx
http://www.codeproject.com/KB/dotnet/managed_unmanaged.aspx

Автор: xvr 23.6.2009, 17:12
В C++ динамическая память ГОРАЗДО хуже, чем в С# по той простой причине, что в C++ нет GC. Любая ошибка в new/delete приведет к утечке памяти или трудноуловимым ошибкам. В .net это проще - нужна память - выделил, не нужна - бросил как есть, система сама подберет  smile 
В stl контейнерах с динамической памятью проще - там слежение за ней берет на себя библиотека (stl), а значит ошибится здесь гораздо сложнее (хотя при большом желании можно  smile )
Если нужно работать с динамически создаваемыми контейнерами и/или объектами, можно применить boost::shared_ptr, но лучше проектировать систему так, что бы такой необходимости не возникало

Автор: Killerman 23.6.2009, 19:43
а де это буст качнуть? и хелп на нево.

Автор: xvr 23.6.2009, 20:11
www.boost.org Help на него в комплекте с ним

Автор: Killerman 24.6.2009, 08:56
спасибо.
Кстати с map<> как то можно узнать значение в ячейке, без проматывания всего списка через итераторы?

ну там типа, какое значение в ячейке m[100].

Автор: azesmcar 24.6.2009, 08:59
Цитата(Killerman @  24.6.2009,  08:56 Найти цитируемый пост)
Кстати с map<> как то можно узнать значение в ячейке, без проматывания всего списка через итераторы?

ну там типа, какое значение в ячейке m[100]. 

Код

map<int, string> m;
map<int, string>::const_iterator it = m.find(100);
if (it != m.end())
   it->second ... //вот значение

Автор: Killerman 24.6.2009, 09:17
Такое я знаю.   smile 
Хотелось  ... = map[100]  smile 

Автор: azesmcar 24.6.2009, 09:20
Цитата(Killerman @  24.6.2009,  09:17 Найти цитируемый пост)
Хотелось  ... = map[100]  smile  

Так тоже можно, но так неправильно. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)