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

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

ru
Offline Offline

« Ответ #60 : 04-09-2009 08:45 » 

Алексей1153++, блин, не понимаю. Приемный поток выделяет необходимый буфер, блокирует очередь, заталкивает запись об буфере, освобождает очередь...  Поток обработки данных блокирует очередь, вынимает все записи о готовых буферах, освобождает очередь, обрабатывает данные, освобождает данные. Что может быть удобнее?
Записан

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

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


« Ответ #61 : 04-09-2009 08:56 » 

sss, удобнее, когда ничего из этих двух строк текста делать не надо )
Это не буфера с данными, а массив элементов (не байтов)
Записан

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

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


WWW
« Ответ #62 : 07-09-2009 03:12 » 

sss, не помню такого или я был молодой и глупый Улыбаюсь
Записан

Странно всё это....
sss
Специалист

ru
Offline Offline

« Ответ #63 : 07-09-2009 04:26 » 

sss, не помню такого или я был молодой и глупый Улыбаюсь

У меня маразм наверное. Извини....
Записан

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

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


« Ответ #64 : 18-09-2009 10:18 » 

если параметр вектора - простой тип
std::vector<BYTE> v;
то гарантируется ли, что все значения обнулены при resize для новых элементов ?
Записан

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

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


WWW
« Ответ #65 : 21-09-2009 02:50 » new

вектор для некоторых операций требует наличие конструктора по умолчанию
к этим операциям относится resize
как это работает?
выделяется новая память туда копируются старые данные, на месте новых данных вызывается inplace new с конструктором по умолчанию, для простых типов это 0, НО не что не мешает иметь вектору специальной перегрузке для простых типов (особенно если вектор из MSVS), хотя стандарт требует вызвать конструктор по умолчанию:
Цитата
void resize(size_type sz);
Effects: If sz < size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz
- size() default constructed elements to the sequence.
Requires: T shall be DefaultConstructible.

предлагаю просто проверить
« Последнее редактирование: 21-09-2009 05:51 от Вад » Записан

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

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


« Ответ #66 : 21-09-2009 05:28 » 

проверить- не проверить, это всё неправильно ) Гарантированно ли там будут нули ?

Ну в любом случае, я инкапсулировал простой тип в свой класс. Чтоб потом не стрельнуло где нибудь ) Неприятно же будет
Записан

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

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


WWW
« Ответ #67 : 21-09-2009 06:30 » 

Алексей1153++, по стандарту гарантировано (точнее гарантирован вызов конструктора по умолчанию), но помнится MS не слишком следует стандартам.
« Последнее редактирование: 21-09-2009 06:33 от LogRus » Записан

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

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


« Ответ #68 : 21-09-2009 08:24 » 

вот то то и оно оно оно Улыбаюсь В общем, оставлю классик с конструкториком
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #69 : 23-12-2009 19:02 » 

Ахренеть!!!! что делается... я чуть со стула не упал... пушистый решил заюзать stl... ЗВЕЗДУ ПУШИСТОМУ!!!!!!!
Ну если есть вопросы пиши!
Записан

С уважением Lapulya
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #70 : 23-12-2009 19:15 » 

lapulya, Мне просто интересно, ты специально ждеш месяца 3, чтоб ответить? Это наверно уже четвертая или пятая старая тема, поднятая тобой только за 1 сутки.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #71 : 23-12-2009 19:29 » 

нет. я просто редко хожу, а что это противозаконно или кого то бесит? Если да, то ок, не буду писать на темы сроком более 2 недель.
Записан

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

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


« Ответ #72 : 24-12-2009 06:15 » 

lapulya, Ага

Финч, да ладно, нормально же пишет
Записан

RXL
Технический
Администратор

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

WWW
« Ответ #73 : 24-12-2009 07:02 » 

lapulya, не надо так уж резко реагировать - Финч только поинтересовался. А вообще, заходи по-чаще Улыбаюсь
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #74 : 28-12-2009 19:11 » 

делаю пул элементов некоего класса s_Knot.
Размер пула меняется шагом в, скажем, 1024 элемента.
Применяю вектор, и ради задуманного пришлось нагородить следующее (шаги огорода пронумерованы)


1)
просто сделать так-
Код:
		typedef std::vector<s_Knot> td_pool;
td_pool m_pool;
нельзя, так как при реаллокации станут невалидны указатели на элементы. Поэтому делаем субконтейнер


2)

Код:
		struct s_Knot_container
{
s_Knot* pk;

private:
void del()
{
if(pk)
{
delete pk;
pk=0;
}
}

public:
s_Knot_container()
{
pk=new s_Knot;
}


~s_Knot_container(){ del(); }

s_Knot_container(const s_Knot_container& src)
{
pk=0;//обязательно
*this=src;
}

void operator =(const s_Knot_container& src)
{
pk=src.pk;
((s_Knot_container*)&src)->pk=0;
}
};

typedef std::vector<s_Knot_container> td_pool;
td_pool m_pool;

но и тут не всё ладно: выясняется, что при реаллокации STL делает:
 - создаёт один экземпляр элемента s_Knot_container (вызывается его конструктор, там выделяется память под один s_Knot)
 - потом STL выделяет место под требуемое количество элементов и КОПИРУЕТ туда во все элементы первый выделенный.
- в итоге - все выделенные элементы вектора имеют  pk==0, а лишь один, нулевой элемент -  pk!=0. Ладно. Далее идём:


3)
 субконтейнер теперь выглядит так
Код:
		struct s_Knot_container
{
s_Knot* pk;

private:
void del()
{
if(pk)
{
delete pk;
pk=0;
}
}

public:
s_Knot_container()
{
pk=0;
}


~s_Knot_container(){ del(); }

s_Knot_container(const s_Knot_container& src)
{
pk=0;//обязательно
*this=src;
}

void operator =(const s_Knot_container& src)
{
if(!pk)
{
if(src.pk)
{
pk=src.pk;
((s_Knot_container*)&src)->pk=0;
}
else
{
pk=new s_Knot;

}
}
}
};

typedef std::vector<s_Knot_container> td_pool;
td_pool m_pool;

теперь, всё, как надо: при переаллокации старые субконтейнеры перекидывают свои данные на "старое" место, не уничтожая свои pk (->s_Knot), затем выделется новая порция субконтейнеров со своими, новыми, s_Knot.
Указатели на s_Knot "не теряются", ведь память в куче не трогается, перекопируются только указатели.


4) ВНИМАНИЕ, вопрос! Моя задача решается как-то проще (с вектором ли или с чем-то ещё из STL) или именно так только и возможно?
« Последнее редактирование: 28-12-2009 19:15 от Алексей1153++ » Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #75 : 28-12-2009 20:05 » 

Ну переопредели оператор = и копирующий конструктор у класса объекта, который хранится в контейнере (в твоем случае s_Knot) и все будет, хотя ихмо это изврат. Более того, если хранить в контейнерах объекты, то положить в них объекты наследников (типа class SUB_s_Knot : public s_Knot) будет некорректно, поскольку они "срежутся" до s_Knot. Короче это геморрой...

Рекомендую хранить в контейнере указатели на объекты (в 99% это лучший вариант для пользовательских типов), а объекты в векторе лучше хранить на стандартные/встроенные типы, которые не переписывают свое содержимое в операторе = и конструкторах, а копируют только ссылки на внутренние ресурсы (ну как std::string) и делают это быстро.

Код:
class MyObject {...};
class MyUBObject : public MyObject {...};

typedef std::vector<MyObject *> MyObjects;
MyObjects objects;
objects.push_back(new MyObject());
objects.push_back(new MySUBObject());

А какова прикладная задача? Почти уверен, что хранение указателей подойдет.

ЗЫ
Цитата
нельзя, так как при реаллокации станут невалидны указатели на элементы.
Реаллокация тут не причем, указатели будут невалидны как только ты попытаешься что-то извлечь из контейнера (тут опять будет создан новый объект)!!! Так что до реаллокации очередь может и не дойти Улыбаюсь
« Последнее редактирование: 28-12-2009 20:23 от lapulya » Записан

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

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


« Ответ #76 : 28-12-2009 20:20 » 

Нет, производных от s_Knot не предвидится. А сама структура содержит только указатели и данные, которые можно при инитке тупо обнулить - я склоняюсь к мысли просто выделять пул в виде байтового массива, кратного структуре, да обнулять этот массив. Ну и завернуть это в класс, который будет возвращать правильные указатели и увеличивать пул, когда надо ) Тогда отпадает вектор и память из кучи разом под много элементов выделяется. Скорость, однако
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #77 : 28-12-2009 20:24 » 

Алексей1153++, Все же непонятно почему бы не хранить указатели. Кстати если ты сейчас не предвидишь наследования от твоего класса (содержимого контейнера), возможно это потребуется позже (но это уже ближе к лирике, но все же). Хранение указателей:
1. полностью решает твою прикладную задачу
2. работает быстро (быстрее только декуе и ничего больше, ну или список, так там и реаллокации нет Улыбаюсь )
3. без проблем расширяется (ну ты прикинь надо будет увеличить структуру на пару членов и т.д.), а тебе с такой "зашивкой" придется попотеть (да еще и не ЗАБЫТЬ исправить во всех местах!!! - безопасность!!!).
4. Ничего дополнительного писать не надо (все уже написано за нас)

Я у своего первого поста еще про реаллокацию дописал.
« Последнее редактирование: 28-12-2009 20:33 от lapulya » Записан

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

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


« Ответ #78 : 28-12-2009 20:41 » 

lapulya, мне обобщения не потребуются, производные тоже, добавление мемберов - тоже вряд ли. Буду экспериментировать, вся ночь впереди )))
Записан

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

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


WWW
« Ответ #79 : 29-12-2009 04:59 » 

4) ВНИМАНИЕ, вопрос! Моя задача решается как-то проще (с вектором ли или с чем-то ещё из STL) или именно так только и возможно?

0. Какая задача.
1. попробуй дек, он не вызывает реалокации при вставке в конец и не ивалидирует иретароры
2. почему бы не использовать контейнер указателей
Код:
boost::ptr_vector<animal> vec;
vec.push_back( new animal ); // you add it as pointer ...
vec[0].eat();                // but get a reference back
3. твой прокси класс, просто умный указатель с передачей владения аля std::auto_ptr
4. ознакомься с советами 1-9 из книги Скотт Мейерс "Эффективное использование STL" взять можно тут http://www.coders-library.ru/uploads/books/public/STL_Meiers.rar
Записан

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

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


« Ответ #80 : 29-12-2009 05:06 » 

LogRus , задача в том, чтобы не выделять память кусочечками много раз, а одним куском про запас. Я сначала думал, что вектор так и делает, но, похоже, ошибался. Поэтому STL сюда таким способом не применим, разве что , действительно, вектор указателей на кусок памяти, где массив элементов был выделен new. Вечером займусь этим вопросом )
Записан

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

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


WWW
« Ответ #81 : 29-12-2009 05:35 » 

1. Можно сделать резерв
2. Можно написать свой аллокатор

Вопрос вот в чём: зачем нужен этот изврат?
Не смотря на то, что у нас в компании высокие требования к скорости кода, мы редко пользуемся аллокаторами и не раньше чем их необходимость будет доказана тестами производительности.

меня почти всегда устраивает deque как контейнер элементов:
1. нет реалокации
2. быстрая вставка в конец
3. память выделяется блоками по несколько элементов
4. не требует больших непрерывных кусков памяти
5. имеет произвольный доступ.

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

вектор так и делает, НО если ты создаёшь пустой вектор, то при вставке первого элемента будет реалокация
стратегия выделения памяти такая, если кончилась, то удвоить
соотвественно, если сделаешь резерв, пускай 2000 элементов, то первые 2000 добавлений не будут вызывать реалокацию

Поэтому STL сюда таким способом не применим

"Ты просто не умеешь их готовить" ©
Записан

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

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


« Ответ #82 : 29-12-2009 05:42 » 

Цитата
необходимость будет доказана тестами производительности.
это я обязательно проведу Улыбаюсь Самому интересно

Цитата
меня почти всегда устраивает deque как контейнер элементов:
1. нет реалокации
2. быстрая вставка в конец
3. память выделяется блоками по несколько элементов
4. не требует больших непрерывных кусков памяти
5. имеет произвольный доступ.
попробую. Пункт 3 мне и нужен


Цитата
элементов, то первые 2000 добавлений не будут вызывать реалокацию
вот вот Улыбаюсь А реаллокация - это потеря указателей, что есть не очень

Цитата
Ты просто не умеешь их готовить
а я и не спорю Улыбаюсь
Записан

RXL
Технический
Администратор

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

WWW
« Ответ #83 : 29-12-2009 09:35 » 

Леш, если элементы из контейнера не удаляются в произвольном порядке, попробуй отказаться от указателей и использовать индексы. Я использую, в основном, vector и map, долговременных указателей не использую и адресую либо через итератор, либо по индексу.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #84 : 29-12-2009 09:41 » 

Можно попробовать. (Но индекс - это дольше, чем указатель)
Записан

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

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


WWW
« Ответ #85 : 29-12-2009 11:23 » 

Можно попробовать. (Но индекс - это дольше, чем указатель)
минимально, опять ты на спичках экономишь
вот смотри разницу обращения по индексу и по указателю.
Код:
int * p = &vector[n];
*p = 8;
................
*(&vector[0] + n) = 8;
................
// или так
int * p = &vector[0];
*(p + n) = 8;
Записан

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

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


« Ответ #86 : 29-12-2009 11:26 » 

LogRus, как всё это снаружи выглядит, я в курсе Улыбаюсь Но оператор [ 0] придётся вызывать каждый раз. А что там внутри у вектора происходит - я не смотрел Улыбаюсь
Записан

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

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


WWW
« Ответ #87 : 29-12-2009 11:40 » 

Алексей1153++, vector[0] это фактически (в релизе) *vector.data
т.е. vector[n] сводится к *(vector.data+n), таже самая работы с чистым указателем, всё как ты любишь
Записан

Странно всё это....
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #88 : 30-12-2009 00:26 » 

Алексей1153++,
Цитата
попробую. Пункт 3 мне и нужен
Если хранить в контейнере объекты (не указатели), то при получении (любым способом) объекта из контейнера ты получишь копию!!! этого объекта, т.е. внешние указатели будут не верны! Если хранить в контейнере поинтеры, то затраты (накладные расходы) на реаллокацию и т.д. (а т.д. = много чего, фактически абсолютно все, что относится так или иначе к манипулированию объектами в контейнере) минимальны + все внешние указатели валидны. Итого, рекомендую хранить поинтеры.

Если это у тебя в приложении ну просто самое узкое место по производительности (такое запросто может быть, могу привести пример их жизни, хотя там скорее дело было в необходимости своего аллокатора) и именно в этом месте эта производительность нужна (что не факт), то:
1. Если кол-во объектов ограничено сверху, то выделяй сразу память под это количество (дальнейшие операции будут максимально быстрыми).
2. Если количество неизвестно, пиши свой аллокатор.
Итого, надо оценить действительно ли данное место нуждается в такой тонкой настройке производительности.
« Последнее редактирование: 30-12-2009 00:28 от lapulya » Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #89 : 30-12-2009 00:37 » 

LogRus,
Я бы так делать не советовал... насколько мне помнится (могу и ошибаться), но

Стандарт гарантирует, что вектор должен выделить последовательный участок памяти для хранения в нем данных, но только это... т.е. ни больше и ни  меньше. То, что вектор обязан выделить массив элементов этого типа и более того, что доступ к i-ому элементу возможен по такому адресу *(vector[0] + i), этого стандарт не гарантирует (во втором я уверен почти на 100% Улыбаюсь ). Да, большинство компиляторов именно так и делают (подозреваю, что так делают все компиляторы), но используя доступ подобным образом программист действует на свой страх и риск. 
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines