![]() |
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]() ![]() ![]() |
|
poiuyt1234 |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 135 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
Пишу прогу. Одна из ее функций анализирует текст. Ищет по определенным условиям слова. Если находит слово заносит его в ячейку массива. Так вот. Слов может быть от 0 до 1000000. Создавать массив с запасом наверно не стоит. А лучше динамически. Но тогда как установить размер массива? При каждом обнаружении нужного слова счетчик будет увеличиваться на еденицу и это слово надо занести в массив.
Можно ли при каждой итерации(обнаружении нужного слова) цикла увеличивать размерность динамического массива на еденицу с помощью setlength ,без потери ранее записанных в него данных? |
|||
|
||||
SneG0K |
|
|||
![]() Max Mara ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1887 Регистрация: 1.12.2007 Где: Wis Dells Репутация: 1 Всего: 54 |
||||
|
||||
Poseidon |
|
|||
![]() Delphi developer ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 5273 Регистрация: 4.2.2005 Где: Гомель, Беларусь Репутация: 53 Всего: 133 |
Изменять размерность массива в большую сторону можно без потери данных. В меншую - нет. Только стоит заметить, что выделение памяти - это очень ресурсоемкая и медленная задача. И если ты на каждую итерацию цикла будешь вызывать setlength, это может оказаться гораздо "тыжелее" и медленнее, чем если бы ты сразу выделил 1000000. Я бы увеличивал размерность блоками. Допустим, по 1000 единиц. Размер блока во многом зависет от того, что будет хранится в массиве. Если сеществует большая вероятность того, что практически все 1000000 будут использованы, то лучше сразу выделять память для 1000000 элементов массива. Если большая вероятность, что элементов будет не более 500000, увеличивать размеронсть по 500000 и т.п. В любом случае, выделить память для 10000 элементов гораздо быстрее, чем 10000 раз выделять память по одному элементу. А вообще, само правильно было бы пронализировать входные данные и выделить ровно столько, сколько надо. Для поставленной задачи это значит "посчитать сколько слов и выделить ровно такое количество элементов". В любом случае будет быстрее, чем делать setlength для каждого слова. -------------------- Если хочешь, что бы что-то работало - используй написанное, если хочешь что-то понять - пиши сам... |
|||
|
||||
Virtuals |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 476 Регистрация: 27.11.2006 Репутация: 3 Всего: 11 |
poiuyt1234,
в дополнение к Poseidon, в двух словах. setlength 1. создает новую переменную требуемого размера 2. копирует в нее содержимое предыдущей переменной 3. уничтожает старую. соответственно для переменной размером в 1000 при setlength 2000? потребуется минимум 1000+2000=3000!!! не забываем об этом. |
|||
|
||||
Alexeis |
|
||||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 109 Всего: 459 |
Все не так просто как кажется, чтобы в этом убедиться можно выполнить следующий код
Память выделяется если ее не хватает, но не возвращается при уменьшении, потому удобно предварительно выделить памяти побольше, это зарезервирует большой блок, затем повторным setLength установить тот размер который вам нужен сейчас, это избавит вас от создании лишней переменной - размера используемой части. В результате мы имеем, то что увеличение размера массива при помощи setLength не будет приводить к перераспределению памяти, а функции High() и Length() будут давать правильный (а не зарезервированный размер). -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
||||
|
|||||
Christoph |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 667 Регистрация: 23.1.2008 Где: Харьков Репутация: 1 Всего: 11 |
Чуть не вкурил,Зачем выделять память побольше? если при нехватки памяти она сама выделить сколько ей надо, ну например выделили память
И это получается что если я туда запишу какое то одно число, а остальная память будет гулять, потому получается что эту память может использоваться массив, хотя могу и ошибаться И например если написать так
Так зачем переживать за память? если присвоится без проблем И еще вот что из кода Alexeis, p1,p2,p3 - выводят начальный адресс массива, я прав? -------------------- ![]() |
||||
|
|||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 192 Всего: 484 |
Поясняю на пальцах:
1. Создаём массив a, размером 1 Получаем в памяти: [a][свободное место] Дальше в работе нам понадобилась переменная i Имеем в памяти: [a][i][свободное место] Теперь мы хотим увеличить массив а до 2. Но вот проблема - место за [a] уже занято. Значит, чтобы увеличить, нужно перенести весь массив [а] туда, где место есть. То есть [ ][i][a ][свободное место] Если массив [a] имеет большой размер, то выделение 1 места приведёт к копированию всего массива, что при большом размере довольно чувствительно. Однако, не вижу особых причин этого боятся в целом алгоритме. При обработке данных в цикле, такое перераспределение произойдёт всего 1 раз, пока массив маленький. Если мы не выделяем постоянно память, то вероятность дальнейших переносов невелика. Хотя, если выделить сразу большой блок, то вовсе исключается. Выделение большого блока, с последующим уменьшением тоже вариант, но тоже не гарантия, хотя снижает количество перераспределений. Впрочем, если счёт идёт не на десятки мегабайт в процессе, чувствительном к задержке в пару-тройку миллисекунд, то я бы и заморачиваться не стал. Всё равно в фиксированном цикле перераспределений немного, а в нефиксированом частота перераспределений невысока. Для массивов до мегабайта это не чувствительно. Поскольку речь идёт о массиве, предельный размер которого 4Мб, то не стоит и голову ломать. На фоне основного алгоритма, перераспределение будет абсолютно нечувствительно. |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 109 Всего: 459 |
Указатель на память массива. Поскольку значение адреса не меняется, то память не перераспределялась. Тут видно что если перваночально памяти было выделено много, то последующие уменьшения и увеличения размера не приводят к перераспределению, пока хватает памяти. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 31 Всего: 88 |
Alexeis, а если так попытаться работать с объемом больше 64-х кило, оно так же работает?
-------------------- Обижено школьников: 8 |
|||
|
||||
poiuyt1234 |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 135 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
а обрезать лишние ячейки тож можно без потери данных в заполненных ячейках с помощью setlength? т.е. понадобилось фактически 700000 из 1000000, а потом setlength(a,700000)
|
|||
|
||||
Riply |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 3 Всего: 32 |
Я бы, наверное, не рискнула быть столь категоричной. SetLength(a, 1000000); SetLength(a, 1); // Здесь "система" считает хвостик свободным и вольна поступать с ним как ей хочеться //... что-то происходит SetLength(a, 10); - перераспределения не произошло, если в "//..." хвостик "системой" не был использован, что может зависеть от расположения звезд ![]() |
|||
|
||||
Christoph |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 667 Регистрация: 23.1.2008 Где: Харьков Репутация: 1 Всего: 11 |
Alexeis, Snowy, спасибо за разъяснения, если кто то может киньте ссылку про менеджер памяти в делфи
-------------------- ![]() |
|||
|
||||
cemick |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 416 Регистрация: 6.7.2006 Где: Санкт-Петербург Репутация: 2 Всего: 6 |
||||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 109 Всего: 459 |
Riply, обычная схема предполагает, что раз один раз понадобилось, то может понадобиться еще раз. Делфийский менеджер памяти не очень любит отдавать память, а при уменьшении размера массива он и вовсе не отдает. Это общая стратегия выделения памяти. Гарантировать такое поведение нельзя, но наедятся можно.
-------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Christoph |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 667 Регистрация: 23.1.2008 Где: Харьков Репутация: 1 Всего: 11 |
Да, но мне интересно почитать ) Прочитал пост Riply и написал код, вроде тот хвостик никто не трогает, хотя немного не уверен
Alexeis, ответил уже ![]() Это сообщение отредактировал(а) Christoph - 18.2.2009, 18:35 -------------------- ![]() |
||||
|
|||||
![]() ![]() ![]() |
Правила форума "Delphi: Общие вопросы" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |