| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    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, мне не нужна очередь, с вектором тут удобнее    Я бы мог самописный диспетчер вроде вектора написать, но решил испробовать вектор, да и время сэкономить. Расширение ? Не предвидится, это разовое использование массива элементов   |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	|  |