Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: контейнеры stl, out of range  (Прочитано 59308 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #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);

всегда корректно сработает, какая длина вектора бы ни была в данный момент ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #32 : 21-08-2009 20:17 » 

я думаю, не проще: метод используется несколько раз в программе, а кроме того, создание временного вектора - как-то некузяво смотрится вообще )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #33 : 21-08-2009 20:18 » 

-1 не лишнее, к примеру:

удалить 1 элемент:
erase(begin(),begin()+1-1);
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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);
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #35 : 21-08-2009 21:01 » 

хм, ладно, по ходу дела проверим ))
Записан

Mayor
Специалист

ru
Offline 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
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #37 : 22-08-2009 07:11 » 

лично мне не нравится надпись  std::vector<BYTE>

CByteVec выглядит компактнее и красивее. Одно это уже повод Улыбаюсь
Записан

Mayor
Специалист

ru
Offline Offline

« Ответ #38 : 22-08-2009 07:24 » 

лично мне не нравится надпись  std::vector<BYTE>

CByteVec выглядит компактнее и красивее. Одно это уже повод Улыбаюсь

typedef std::vector<BYTE> CByteVec
Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #39 : 22-08-2009 08:27 » 

разницы нет. А кроме того, класс удобнее - он расширяем
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #40 : 26-08-2009 07:37 » 

вопросик по вектору:

Поскольку вектор - это как бы резиновый буфер, то есть, когда добавляем данные , а они не влазять, происходит реаллокация. Но когда данные обработаны, и происходит очередной, скажем, resize(10) , что при этом делается с "балластной" озу ? Так и будет большой выделенный хвост висеть, ведь я могу им больше не пользоваться (принял, скажем, из сокета один раз 10000 байт, а потом только по 10 байтиков дальше)
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #42 : 26-08-2009 08:29 » 

понятно, спасибо
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #43 : 27-08-2009 03:28 » 

но если ты будешь делать такое много-много-много раз, то знай это плохое решение ибо фрагментация
я бы использовал дек
в любом случае выбор контейнера должен сопровождаться пониманием последствий
поэтому обычно делаю
typedef std::vector<long> Container;

если, что можно оптимизировать малой кровью в одной точке кода (сменив контейнер, аллокатор, для ассоциативных контейнеров метод сортировки)
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #44 : 27-08-2009 04:04 » 

я бы использовал дек
а это шо ?

Ну тайпдеф у меня присутствует в виде класса, так что тут всё схвачено )

Часто делать не требуется, например может придти большой файл, вектор растянется на метр. А потом целый день будут приходить сообщения по несколько байт.
а фрагментация озу- чем опасна ? Ведь вектор то всё равно сплошной остаётся
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #45 : 27-08-2009 06:26 » 

Дек - это std::deque. Отличается от вектора моделью работы с памятью. Использует не один непрерывный блок, а цепочку небольших блоков. В связи с этим, не гарантирует непрерывность буфера, взамен же предоставляет быструю вставку в начало и конец контейнера. Ну и подчищает пустые блоки.

Насчёт часто - не часто: а каков критерий для resize тогда? Различие между имеющимся и требуемым размером на порядки в пользу первого?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #46 : 27-08-2009 06:35 » 

критерий, скажем, такой:
задаёмся константой, пусть 4096.
Если в векторе лежит данных меньше константы, то подгоняем размер к константе.
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #47 : 27-08-2009 07:47 » 

Понятно Улыбаюсь
А фрагментация ОЗУ опасна тем же, чем и любая другая фрагментация: потерей производительности и неэффективным расходом памяти. Чем больше мелких блоков выделяется-освобождается, тем меньше остаётся крупных участков между ними, и выделить крупный блок при вроде бы большом количестве доступной памяти становится труднее. Плюс, своп тоже будет расти в соответствии с ростом объёма требуемой памяти.
Кстати, оптимизация-дефрагментация используемой памяти - это, пожалуй, одна из основных причин для применения внешних (отличных от дефолта) аллокаторов для контейнеров (в основном, для связных списков и ассоциативных контейнеров). Например, для распределения памяти под нужды контейнера из некоторого пула, управляющего относительно крупными блоками.
« Последнее редактирование: 27-08-2009 07:53 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #48 : 27-08-2009 08:12 » 

короче, дело ясное, что дело тёмное Улыбаюсь
Но мой вариант хорошо поддаётся применению: допустим, пришлось принять 2 метра, пусть даже озу под это выделилось фрагментированно. После обработки возвращаем в 4096, а циферка это относительно маленькая, поэтому новый буфер заткнёт собой какой нибудь просвет в озу.

Ещё мысль - иметь постоянного размера вектор [4096] , а при необходимости получить данных больше -создавать временный вектор большого размера, копировать туда постоянный вектор и продолжать работать с большим. Когда большой опустошается или становится меньше 4096, его копируем обратно в постоянный и мочим

С пулом сложнее - я пока ещё не знаю, как так сделать. И это же ещё придётся этот пул постоянно выделенным держать
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #49 : 27-08-2009 08:30 » 

Если тебе всё-таки нужна большая непрерывная область памяти - про пулы можно даже не думать. Тем более что минимальный размер в 4КБ - не такой уж и маленький блок.

Про реализацию пулов можно почитать у Александреску, "Современное проектирование на C++" (Modern C++ design), 4я глава. Там подробно разобрана тема оптимизации выделения памяти для маленьких объектов.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #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++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #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++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #52 : 03-09-2009 15:43 » 

ещё загадка:
Код:
std::vector<A> v1;
v1.resize(10);
...
...



на строке v1.resize(10);  два раза вызывается деструктор ~A
почемур ? Причём это связано явно не с уничтожением локального вектора
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #53 : 04-09-2009 04:23 » 

я вижу несколько решений:
1. Конструктор копирования
2. Конструктор копирования с передачей владения
3. Конструктор копирования + boost::shared_ptr
4. выкинуть указатель Улыбаюсь
5. еще что-нибуть эдакое Улыбаюсь

на строке v1.resize(10);  два раза вызывается деструктор ~A
почемур ? Причём это связано явно не с уничтожением локального вектора

надо смотреть в конкретную реализацию вектора
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #54 : 04-09-2009 04:34 » 

указатель выкинуть не получится )
С конструктором копирования щас попробую
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #55 : 04-09-2009 04:41 » 

ага, помогло )

Код:
A(const A& src)
{
*this=A;
((A*)&src)->pX=0;
}

только странно , я вроде пробовал до задания вопроса что то подобное, но почему то не помогло )) Может косячил
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #56 : 04-09-2009 06:29 » 

Код:
pX = src.pX;
src.pX=0;
так понятней.
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #57 : 04-09-2009 06:48 » 

понятней, но не скомпилируется и работать не будет Улыбаюсь В X не только указатель
Записан

sss
Специалист

ru
Offline Offline

« Ответ #58 : 04-09-2009 08:23 » 

Алексей1153++, зачем ты так упрямо пытаешься использовать вектор? Попробуй месить с очередью... Если прям так необходимо использовать STL - используй std::queue... Не будет проблем с расширением.

я вижу несколько решений:
1. Конструктор копирования
2. Конструктор копирования с передачей владения
3. Конструктор копирования + boost::shared_ptr

Помниться кто-то пытался аргументировать неприемлемость полиморфизма накладными расходами на виртуальные вызовы.... А это значит решение, да. "Простой" и "красивый" STL Аминь!.

Записан

while (8==8)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #59 : 04-09-2009 08:32 » 

sss, мне не нужна очередь, с вектором тут удобнее Улыбаюсь Я бы мог самописный диспетчер вроде вектора написать, но решил испробовать вектор, да и время сэкономить.
Расширение ? Не предвидится, это разовое использование массива элементов Улыбаюсь
Записан

Страниц: 1 [2] 3 4   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines