| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Можно ли задавать размер динамического массива |
| Автор: poiuyt1234 17.2.2009, 20:39 |
| Пишу прогу. Одна из ее функций анализирует текст. Ищет по определенным условиям слова. Если находит слово заносит его в ячейку массива. Так вот. Слов может быть от 0 до 1000000. Создавать массив с запасом наверно не стоит. А лучше динамически. Но тогда как установить размер массива? При каждом обнаружении нужного слова счетчик будет увеличиваться на еденицу и это слово надо занести в массив. Можно ли при каждой итерации(обнаружении нужного слова) цикла увеличивать размерность динамического массива на еденицу с помощью setlength ,без потери ранее записанных в него данных? |
| Автор: SneG0K 17.2.2009, 20:53 |
Да. Предыдущие данные не теряются. |
| Автор: Virtuals 18.2.2009, 07:42 |
| poiuyt1234, в дополнение к Poseidon, в двух словах. setlength 1. создает новую переменную требуемого размера 2. копирует в нее содержимое предыдущей переменной 3. уничтожает старую. соответственно для переменной размером в 1000 при setlength 2000? потребуется минимум 1000+2000=3000!!! не забываем об этом. |
| Автор: Alexeis 18.2.2009, 10:47 | ||||
Все не так просто как кажется, чтобы в этом убедиться можно выполнить следующий код
Память выделяется если ее не хватает, но не возвращается при уменьшении, потому удобно предварительно выделить памяти побольше, это зарезервирует большой блок, затем повторным setLength установить тот размер который вам нужен сейчас, это избавит вас от создании лишней переменной - размера используемой части. В результате мы имеем, то что увеличение размера массива при помощи setLength не будет приводить к перераспределению памяти, а функции High() и Length() будут давать правильный (а не зарезервированный размер). |
| Автор: Christoph 18.2.2009, 15:29 | ||||
Чуть не вкурил,Зачем выделять память побольше? если при нехватки памяти она сама выделить сколько ей надо, ну например выделили память
И это получается что если я туда запишу какое то одно число, а остальная память будет гулять, потому получается что эту память может использоваться массив, хотя могу и ошибаться И например если написать так
Так зачем переживать за память? если присвоится без проблем И еще вот что из кода Alexeis, p1,p2,p3 - выводят начальный адресс массива, я прав? |
| Автор: Snowy 18.2.2009, 15:50 |
| Поясняю на пальцах: 1. Создаём массив a, размером 1 Получаем в памяти: [a][свободное место] Дальше в работе нам понадобилась переменная i Имеем в памяти: [a][i][свободное место] Теперь мы хотим увеличить массив а до 2. Но вот проблема - место за [a] уже занято. Значит, чтобы увеличить, нужно перенести весь массив [а] туда, где место есть. То есть [ ][i][a ][свободное место] Если массив [a] имеет большой размер, то выделение 1 места приведёт к копированию всего массива, что при большом размере довольно чувствительно. Однако, не вижу особых причин этого боятся в целом алгоритме. При обработке данных в цикле, такое перераспределение произойдёт всего 1 раз, пока массив маленький. Если мы не выделяем постоянно память, то вероятность дальнейших переносов невелика. Хотя, если выделить сразу большой блок, то вовсе исключается. Выделение большого блока, с последующим уменьшением тоже вариант, но тоже не гарантия, хотя снижает количество перераспределений. Впрочем, если счёт идёт не на десятки мегабайт в процессе, чувствительном к задержке в пару-тройку миллисекунд, то я бы и заморачиваться не стал. Всё равно в фиксированном цикле перераспределений немного, а в нефиксированом частота перераспределений невысока. Для массивов до мегабайта это не чувствительно. Поскольку речь идёт о массиве, предельный размер которого 4Мб, то не стоит и голову ломать. На фоне основного алгоритма, перераспределение будет абсолютно нечувствительно. |
| Автор: Alexeis 18.2.2009, 15:56 | ||
Указатель на память массива. Поскольку значение адреса не меняется, то память не перераспределялась. Тут видно что если перваночально памяти было выделено много, то последующие уменьшения и увеличения размера не приводят к перераспределению, пока хватает памяти. |
| Автор: bems 18.2.2009, 17:41 |
| Alexeis, а если так попытаться работать с объемом больше 64-х кило, оно так же работает? |
| Автор: poiuyt1234 18.2.2009, 17:58 |
| а обрезать лишние ячейки тож можно без потери данных в заполненных ячейках с помощью setlength? т.е. понадобилось фактически 700000 из 1000000, а потом setlength(a,700000) |
| Автор: Riply 18.2.2009, 17:58 | ||
Я бы, наверное, не рискнула быть столь категоричной. SetLength(a, 1000000); SetLength(a, 1); // Здесь "система" считает хвостик свободным и вольна поступать с ним как ей хочеться //... что-то происходит SetLength(a, 10); - перераспределения не произошло, если в "//..." хвостик "системой" не был использован, что может зависеть от расположения звезд |
| Автор: Christoph 18.2.2009, 17:59 |
| Alexeis, Snowy, спасибо за разъяснения, если кто то может киньте ссылку про менеджер памяти в делфи |
| Автор: cemick 18.2.2009, 18:08 |
вроде менеджер памяти тут не причем(вроде как), все делается в DynArraySetLength в System.. |
| Автор: Alexeis 18.2.2009, 18:28 |
| Riply, обычная схема предполагает, что раз один раз понадобилось, то может понадобиться еще раз. Делфийский менеджер памяти не очень любит отдавать память, а при уменьшении размера массива он и вовсе не отдает. Это общая стратегия выделения памяти. Гарантировать такое поведение нельзя, но наедятся можно. |
| Автор: Christoph 18.2.2009, 18:33 | ||||
Да, но мне интересно почитать ) Прочитал пост Riply и написал код, вроде тот хвостик никто не трогает, хотя немного не уверен
Alexeis, ответил уже |
| Автор: Riply 18.2.2009, 18:46 |
Полностью согласна. Дык, под "зависит от расположения звезд" я и имела ввиду, что нам остается только надеяться |
| Автор: Bose 18.2.2009, 18:51 |
Посмотри пост в блоге http://vingrad.ru/users/CodeMonkey: http://gunsmoker.blogspot.com/2009/01/blog-post.html и обязательно пройдись по ссылочкам из этого поста. |
| Автор: Christoph 18.2.2009, 19:03 |
| Bose, спасибо |
| Автор: Uridian 19.2.2009, 19:20 | ||
Почему бы не использовать для хранения найденных слов объект класса TStringList вместо динамического массива? |