| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Динамический массив |
| Автор: Baa 25.12.2002, 19:07 |
| Есть у нас динамический массив... char* lpBuffer = new char [0xFF]; И он у нас заполнен чем-то (не важно чем). Далее, нам надо его расширить... lpBuffer = new char [0x200]; но вот беда, данные-то потерялись Вопрос: можно ли как-то обойтись без временного второго массива? |
| Автор: Step 25.12.2002, 19:37 |
| думаю что нельзя ведь нею выделяет тебе новую область памяти, разве что если ты уверен что у тебя после твоего массива память не используется, можеш попробувать создать масив на больше как ты это делал, потом его удаляеш, и указатель ставиш на первый масив, память тажа, но элементов больше. |
| Автор: Alex101 25.12.2002, 20:49 |
| Ежели говорить о реализации вообще (не опираясь на конкретный язык или его реализацию), то нельзя - память-то RAM, все ухищрения приведут к одному и тому же - сначала часть выделенной памяти не будет использоваться. А так - есть классы, позволяющие это реализовывать. ЗЫ Делал я программу под ДОС, она работала в графическом режиме, использовал текстовый буфер для хранения данных. Но это так, к слову пришлось |
| Автор: AntonSaburov 25.12.2002, 20:52 |
| Для таких случаев можно использовать STL - std::vector<char> И никаких проблем больше нет |
| Автор: Baa 25.12.2002, 21:03 |
| Тош, дык можно и CArray... а мне вот хоца без излишеств (MFC, ATL и т.д.)... но как я понял, в любом случае, получается камасутра, а усложнять код не стоит... |
| Автор: Alex101 25.12.2002, 21:11 | ||
Ежели приложение небольшое, то конечно. А иначе - лучше перегрузить немного, но будет удобнее работать и за отладкой меньше времени просидишь. |
| Автор: AntonSaburov 25.12.2002, 21:24 | ||
STL - это уже стандарт, который есть практически на всех сишных компиляторах. Так что вполне нормально его использовать. Тем более если проект достаточно большой, то смысл изобретать велосипед. |
| Автор: Baa 25.12.2002, 21:49 |
| Дык проект небольшой |
| Автор: dim 25.12.2002, 21:49 |
| Ну можно еще написать класс массива, в котором к примеру, перегрузить операторы new и delete. Оператор new перегрузить таким образом, что если он вызывается первый раз, то вызывать HeapAlloc, все последующие разы вызываем HeapReAlloc. Затраты конечно же будут, но в kernel mode менее ощутимо чем в user mode. К тому же можно интеллектуально использовать флаг HEAP_REALLOC_IN_PLACE_ONLY. Первый раз HeapReAlloc вызываем с этим флагом (т.е. пытаемся увеличить размер не перенося содержимое), если не вышло то вызываем HeapReAlloc уже без этого флага. |
| Автор: suborg 26.12.2002, 03:20 |
| Точно нельзя потому что массив в данном случае - непрерывная область памяти, но система работы кучей умеет выделять память не только из хвоста кучи, но и из дырок при фрагментации памяти в процессе работы программы, таким образом ты никогда не застрахован от того, что вслед за твоим массивом идут другие данные, следовательно по тому же адресу выделить массив другого размера нельзя, значит придется делать новый массив. |
| Автор: dim 26.12.2002, 03:52 |
| Да, но в том случае если за массивом дырка переноса не будет, т.е при перевыделении есть значительная вероятность что переноса не будет, тогда как при простом ремейке перенос будет всегда. |
| Автор: Fantasist 26.12.2002, 07:31 | ||
dim, правильно сказал. Даже если ты хочешь самы простой массив - все равно его лучше обернуть в класс. Идея по реализации, правда, была предложенна весьма геморная.
Реализация realloc зависит от задачи(как, на самом деле, и реализация аллокации). Если это будет использоваться только с простыми типами, то подойдет почти любой способ - и с вин API и с malloc/realloc и также new/delete/memcpy. Если будут использоваться массивы классов, то надо вызывать конструкторы и деструкторы, а при реаллокации еще и поэлементно копировать (с помощью operator=), но для этого надо знать сколько копировать, а значит либо хранить длинну внутри класса, либо.... |
| Автор: Nastya 26.12.2002, 22:54 |
| Есть два варианта: 1. Прользоваться new, но перед повторным выдлением памяти копировать массив во временный, удалять его, создавать новы и копировать наместо. 2. Пользоваться функциями malloc и realloc из библионтеки stdlib |
| Автор: Baa 27.12.2002, 00:24 | ||
Насть, дык я ж грю, что эти варианты не подходят... мне-то было интересно, можно ли с помощью new... а другие варианты я и сам знаю з.ы. сам делаю через временный массив (если токо с winapi). |
| Автор: dim 27.12.2002, 04:26 | ||||
Один раз реализовать, а потом можно использовать. Вот пример:
|
| Автор: Fantasist 27.12.2002, 05:00 |
| Ой-ой. По-моему, плохая реализация. Зачем перегружать new/delete? Зачем делать все static? Почти никакой инкапсуляции. Пользоваться таким массивом очень неудобно. Все равно приходиться вызывать new/delete плюс к этому, надо вызывать SetVector и Release. Для своих классов его опять же использовать нельзя - объекты не конструируются. А для простых типов, так лучше использовать std::valarray или сделать свою простую версию, как я предложил используя malloc/realloc/memcpy. |
| Автор: dim 27.12.2002, 05:26 | ||||||
Как раз затем, чтобы с ним было удобно работать.
Демагогическое утверждение. Initialize и Release вызываются всего один раз, SetVector лишь в том случае если использются несколько массивов (т. е при правильной проектировке это вообще это не будет вызывать никаких неприятностей).
Я не ставил себе задачу построить универсальный класс, рассчитаный еще и на custom типы, но очевидно что при желании его можно допилить до этого. Хотя это не существенно, поскольку для подобных задач существуют стандартные классы типа std::vector, а я предлагал решение по первоначальной постановке задачи. Что касается malloc/realloc кака по мне то это неудобно. |
| Автор: Baa 27.12.2002, 17:12 |
| Хорошо, с этим все понятно... можно разработать свой класс/шаблон или пользоваться уже существующими. А как это реализовано в CArray? з.ы. в исходники пока не лез. |
| Автор: AntonSaburov 27.12.2002, 21:31 | ||
А чего там лезть - тот же template, что-то типа Vector. Нормальное использование STL. Дольше обсуждаем, чем делаем |
| Автор: dim 27.12.2002, 21:57 | ||
А вот так как раз реализовано обычным копированием (переносим старые данные, аллоцируем новый размер и переносим все обратно). |
| Автор: Baa 28.12.2002, 01:21 | ||
Все уже дааавно сделано |
| Автор: Fantasist 28.12.2002, 05:18 | ||||||||||
Прювет. Люди придумывают столько разных инкапсуляторов, для того чтобы НЕ вызывать самим new/delete (при исключениях это особенно удобно), а вы в нагрузку предлагаете еще и два метода вызывать. Если мне захочется пользоваться вашим классом, мне придется писать еще обертку к нему.
Вы что, хотите сказать, что в программе обычно используется всего лишь ОДИН массив?
При правильной проектировке, такого класса, как у вас, не будет.
По этому вопросу, я бы сказал, что этим вопросом не стоит задаваться. Все равно чаще всего будет выделение/копирование. Это не та вещь которую надо оптимизировать. Оптимизировать надо частоту перераспределения памяти. То есть, чтобы поменьше приходилось изменять размер массива.
Не думаю, что так много. Скорее всего: аллоцируем новую память, копируем в нее старые данные (и конструируем новые элементы). Не зачем данные туда и обратно таскать. |
| Автор: dim 30.12.2002, 21:12 | ||
У меня такое ощущение, что ты вообще не читал о чем идет речь в топике. Кстати я и не заставляю пользоваться тебя своим классом. Мне вообщем-то такие извращения на фиг не нужны и я сторонник использования старого доброго того что уже сделано и проверено, но был вопрос и я постарался дать на него ответ, но не спорить о том как лучше организовывать классы враперы. Это вообщем попахивает офтопиком. |
| Автор: Vaulter 31.12.2002, 05:18 |
| Baa на самом деле STL сделает так, что любые твои ручные ухищрения окажутся в конечном итоге больше, медленее и неудобнее. |
| Автор: Fantasist 31.12.2002, 06:01 | ||
Хе-хе. |
| Автор: Fantasist 31.12.2002, 06:21 | ||
Ок. |
| Автор: Baa 31.12.2002, 17:11 |
| Всем спасибо за обсуждение. |