Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #30 : 21-08-2009 19:58 » |
|
ради одного метода (вырезать нужное количество элементов с начала вектора), который не нашёл в векторе, написал класс class CByteVec:public std::vector<BYTE> { public: //объявляем часть данных в начале буфера ненужной //хвост сдвигается в начало void CropBegin(DWORD dwdBeginLen) { if(dwdBeginLen>0) { if(dwdBeginLen>=size()) { clear(); } else { erase(begin(),begin()+dwdBeginLen-1); } } } };
может это всё лишнее и строка erase(begin(),begin()+dwdBeginLen-1); всегда корректно сработает, какая длина вектора бы ни была в данный момент ?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #31 : 21-08-2009 20:12 » |
|
А не проще поступить в духе std::vector<BYTE> vec; // ... vec.erase( vec.begin(), (vec.size() > dwdBeginLen) ? vec.begin() + dwdBeginLen : vec.end() );
ну, или, если не нравится, std::vector<BYTE> vec; // ... if(dwdBeginLen>=vec.size()) { vec.clear(); } else { std::vector<BYTE> temp (vec.begin()+dwdBeginLen, vec.end()); vec.swap(temp); }
Главное - не пойму, стоило из-за этого класс разводить? По-моему, хватило бы и функции. Кстати, в твоём примере вычитать 1 - совершенно излишне. Поскольку удаляемый диапазон - [first, last)
|
|
« Последнее редактирование: 21-08-2009 20:14 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #32 : 21-08-2009 20:17 » |
|
я думаю, не проще: метод используется несколько раз в программе, а кроме того, создание временного вектора - как-то некузяво смотрится вообще )
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #33 : 21-08-2009 20:18 » |
|
-1 не лишнее, к примеру:
удалить 1 элемент: erase(begin(),begin()+1-1);
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #34 : 21-08-2009 20:54 » |
|
-1 не лишнее, к примеру:
удалить 1 элемент: erase(begin(),begin()+1-1);
Документация на STL говорит, что это не так // erase the first 3 elements: myvector.erase (myvector.begin(),myvector.begin()+3);
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #35 : 21-08-2009 21:01 » |
|
хм, ладно, по ходу дела проверим ))
|
|
|
Записан
|
|
|
|
Mayor
Специалист
Offline
|
|
« Ответ #36 : 22-08-2009 03:12 » |
|
ради одного метода (вырезать нужное количество элементов с начала вектора), который не нашёл в векторе, написал класс
может это всё лишнее и строка erase(begin(),begin()+dwdBeginLen-1);
всегда корректно сработает, какая длина вектора бы ни была в данный момент ?
-1 тут лишняя, тк erase не обращается к объекту на который ссылается правый итератор ( те он может быть == end(), как и во всех остальных перебирающих функциях ) так что кода: if (dwb>=size() ) clear(); else erase(begin(),begin()+dwb); вполне хватит, ну если хочешь оптимизировать - то можешь вычесть из size() -1 и честно говоря тоже не понял, зачем тебе для этого кода целый класс
|
|
|
Записан
|
1n c0de we trust
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #37 : 22-08-2009 07:11 » |
|
лично мне не нравится надпись std::vector<BYTE> CByteVec выглядит компактнее и красивее. Одно это уже повод
|
|
|
Записан
|
|
|
|
Mayor
Специалист
Offline
|
|
« Ответ #38 : 22-08-2009 07:24 » |
|
лично мне не нравится надпись std::vector<BYTE> CByteVec выглядит компактнее и красивее. Одно это уже повод typedef std::vector<BYTE> CByteVec
|
|
|
Записан
|
1n c0de we trust
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #39 : 22-08-2009 08:27 » |
|
разницы нет. А кроме того, класс удобнее - он расширяем
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #40 : 26-08-2009 07:37 » |
|
вопросик по вектору:
Поскольку вектор - это как бы резиновый буфер, то есть, когда добавляем данные , а они не влазять, происходит реаллокация. Но когда данные обработаны, и происходит очередной, скажем, resize(10) , что при этом делается с "балластной" озу ? Так и будет большой выделенный хвост висеть, ведь я могу им больше не пользоваться (принял, скажем, из сокета один раз 10000 байт, а потом только по 10 байтиков дальше)
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #41 : 26-08-2009 08:15 » |
|
Да, так и будет висеть хвост. Как резерв на случай нового увеличения, чтобы не делать реаллокаций опять. Если хочешь обрезать хвост - используй swap вместо resize. Выглядит примерно так: typedef std::vector<mytype> myvec; myvec vec(10000); // пусть здесь лежит 10 тысяч элементов
vec.swap( myvec(vec.begin(), vec.begin() + 10 );
На выходе в vec оказываются 10 элементов (и сам он длиной 10), а длинный буфер удаляется вместе с временной переменной.
|
|
« Последнее редактирование: 26-08-2009 08:17 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #42 : 26-08-2009 08:29 » |
|
понятно, спасибо
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #43 : 27-08-2009 03:28 » |
|
но если ты будешь делать такое много-много-много раз, то знай это плохое решение ибо фрагментация я бы использовал дек в любом случае выбор контейнера должен сопровождаться пониманием последствий поэтому обычно делаю typedef std::vector<long> Container;
если, что можно оптимизировать малой кровью в одной точке кода (сменив контейнер, аллокатор, для ассоциативных контейнеров метод сортировки)
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #44 : 27-08-2009 04:04 » |
|
я бы использовал дек
а это шо ? Ну тайпдеф у меня присутствует в виде класса, так что тут всё схвачено ) Часто делать не требуется, например может придти большой файл, вектор растянется на метр. А потом целый день будут приходить сообщения по несколько байт. а фрагментация озу- чем опасна ? Ведь вектор то всё равно сплошной остаётся
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #45 : 27-08-2009 06:26 » |
|
Дек - это std::deque. Отличается от вектора моделью работы с памятью. Использует не один непрерывный блок, а цепочку небольших блоков. В связи с этим, не гарантирует непрерывность буфера, взамен же предоставляет быструю вставку в начало и конец контейнера. Ну и подчищает пустые блоки.
Насчёт часто - не часто: а каков критерий для resize тогда? Различие между имеющимся и требуемым размером на порядки в пользу первого?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #46 : 27-08-2009 06:35 » |
|
критерий, скажем, такой: задаёмся константой, пусть 4096. Если в векторе лежит данных меньше константы, то подгоняем размер к константе.
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #47 : 27-08-2009 07:47 » |
|
Понятно А фрагментация ОЗУ опасна тем же, чем и любая другая фрагментация: потерей производительности и неэффективным расходом памяти. Чем больше мелких блоков выделяется-освобождается, тем меньше остаётся крупных участков между ними, и выделить крупный блок при вроде бы большом количестве доступной памяти становится труднее. Плюс, своп тоже будет расти в соответствии с ростом объёма требуемой памяти. Кстати, оптимизация-дефрагментация используемой памяти - это, пожалуй, одна из основных причин для применения внешних (отличных от дефолта) аллокаторов для контейнеров (в основном, для связных списков и ассоциативных контейнеров). Например, для распределения памяти под нужды контейнера из некоторого пула, управляющего относительно крупными блоками.
|
|
« Последнее редактирование: 27-08-2009 07:53 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #48 : 27-08-2009 08:12 » |
|
короче, дело ясное, что дело тёмное Но мой вариант хорошо поддаётся применению: допустим, пришлось принять 2 метра, пусть даже озу под это выделилось фрагментированно. После обработки возвращаем в 4096, а циферка это относительно маленькая, поэтому новый буфер заткнёт собой какой нибудь просвет в озу. Ещё мысль - иметь постоянного размера вектор [4096] , а при необходимости получить данных больше -создавать временный вектор большого размера, копировать туда постоянный вектор и продолжать работать с большим. Когда большой опустошается или становится меньше 4096, его копируем обратно в постоянный и мочим С пулом сложнее - я пока ещё не знаю, как так сделать. И это же ещё придётся этот пул постоянно выделенным держать
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #49 : 27-08-2009 08:30 » |
|
Если тебе всё-таки нужна большая непрерывная область памяти - про пулы можно даже не думать. Тем более что минимальный размер в 4КБ - не такой уж и маленький блок.
Про реализацию пулов можно почитать у Александреску, "Современное проектирование на C++" (Modern C++ design), 4я глава. Там подробно разобрана тема оптимизации выделения памяти для маленьких объектов.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #50 : 03-09-2009 11:14 » |
|
struct A { const X* pX;
A() { pX=0; }
~A() { if(pX) { delete pX; pX=0; } } };
std::vector<A> v;
v.resize(1); v[0].pX=new X;
v.resize(2); //<<<
на последней строчке происходит следующее: -вызывается деструктор для первого элемента и мочит *pX -создаются 2 новых элемента как предотвратить вызов деструктора то ?
|
|
« Последнее редактирование: 03-09-2009 14:55 от Алексей1153++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #51 : 03-09-2009 15:01 » |
|
пока нашёл такой вызод struct A { const X* pX; bool bDontUseDtr;
A() { pX=0; bDontUseDtr=false; }
~A() { if(pX && !bDontUseDtr) { delete pX; pX=0; } } };
std::vector<A> v;
v.resize(1); v[0].pX=new X;
//...
for(DWORD i=0;i<v.size();i++) { v[i].bDontUseDtr=true; }
v.resize(2); //деструкторы отключены
for(DWORD i=0;i<v.size();i++) { v[i].bDontUseDtr=false; }
ну а при уменьшении размера не лочить те элементы, которые должны удалиться (они в конце), иначе будет утечка
|
|
« Последнее редактирование: 03-09-2009 16:01 от Алексей1153++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #52 : 03-09-2009 15:43 » |
|
ещё загадка: std::vector<A> v1; v1.resize(10); ... ...
на строке v1.resize(10); два раза вызывается деструктор ~A почемур ? Причём это связано явно не с уничтожением локального вектора
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #53 : 04-09-2009 04:23 » |
|
я вижу несколько решений: 1. Конструктор копирования 2. Конструктор копирования с передачей владения 3. Конструктор копирования + boost::shared_ptr 4. выкинуть указатель 5. еще что-нибуть эдакое на строке v1.resize(10); два раза вызывается деструктор ~A почемур ? Причём это связано явно не с уничтожением локального вектора
надо смотреть в конкретную реализацию вектора
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #54 : 04-09-2009 04:34 » |
|
указатель выкинуть не получится ) С конструктором копирования щас попробую
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #55 : 04-09-2009 04:41 » |
|
ага, помогло ) A(const A& src) { *this=A; ((A*)&src)->pX=0; }
только странно , я вроде пробовал до задания вопроса что то подобное, но почему то не помогло )) Может косячил
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #56 : 04-09-2009 06:29 » |
|
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #57 : 04-09-2009 06:48 » |
|
понятней, но не скомпилируется и работать не будет В X не только указатель
|
|
|
Записан
|
|
|
|
sss
Специалист
Offline
|
|
« Ответ #58 : 04-09-2009 08:23 » |
|
Алексей1153++, зачем ты так упрямо пытаешься использовать вектор? Попробуй месить с очередью... Если прям так необходимо использовать STL - используй std::queue... Не будет проблем с расширением. я вижу несколько решений: 1. Конструктор копирования 2. Конструктор копирования с передачей владения 3. Конструктор копирования + boost::shared_ptr
Помниться кто-то пытался аргументировать неприемлемость полиморфизма накладными расходами на виртуальные вызовы.... А это значит решение, да. "Простой" и "красивый" STL .
|
|
|
Записан
|
while (8==8)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #59 : 04-09-2009 08:32 » |
|
sss, мне не нужна очередь, с вектором тут удобнее Я бы мог самописный диспетчер вроде вектора написать, но решил испробовать вектор, да и время сэкономить. Расширение ? Не предвидится, это разовое использование массива элементов
|
|
|
Записан
|
|
|
|
|