![]() |
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]() ![]() ![]() |
|
EKoshelev |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 509 Регистрация: 1.9.2004 Репутация: нет Всего: нет |
Доброго дня.
Возник вопрос: можно ли сделать класс (или набор процедур и функций) работающий с любыми динамическими массивами. То есть имея динамический массив типа Integer, или типа какой-нибудь хитрой структуры я бы при помощи одних и тех же средств мог добавлять элемент, удалять искать и т. п. Чуть конкретнее. Массивы будут создаваться по стандартной схеме: arr1: array of integer; arr2: array of TObject; arr3: array of record a, b, c: double; b: array [0..4] of boolean; end; Далее я буду передавать arr1, arr2 и arr3 в какие-то функции, и с ними будут происходить необходимые преобразования. При этом во всех трёх случаях, например, для добавления элемента я буду вызывать одну и ту же процедуру. В принципе, мне почти всё понятно за исключением одного момента. Не понятно как изменить длину массива. Дело в том, что если массивы с разными элементами будут передаваться в одну процедуру, то процедура должна будет воспринимать как указатели (по крайней мере, лично я других вариантов не вижу). При этом воспользоваться функцией SetLength я не смогу (хотя вот прямо сейчас подумал, что можно попробовать извратиься). Короче, если бы знать как изменить длину массива не используя SetLength, то, вероятно, все мои проблемы решились бы. Короче, если кто-то может чем-то помочь, то я был бы благодарен. Ну, естественно, если уже есть решения, то ссылки были бы не лишними. Заранее спасибо. -------------------- Вежливым и адекватным предлагаю общаться на "ты". |
|||
|
||||
AndreyIQ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 185 Регистрация: 5.2.2007 Репутация: нет Всего: 8 |
Вам точно массив нужен? Может TList проще будет?
|
|||
|
||||
EKoshelev |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 509 Регистрация: 1.9.2004 Репутация: нет Всего: нет |
AndreyIQ, Ну а как без напрягов в TList'е можно хранить int64 или структуры? Если только по ссылкам. При этом (если я ошибаюсь - поправь) постоянно нужно будет преобразовывать типы. Я как-то (с помощью TList) накидал класс хранящий interger'ы, и вместо Pointer'ов хранил integer'ы. Получилось удобно, но не скоро. Каждый раз писать новый класс для нового типа - не охота и долго. А при таком подходе, полагаю, можно всё будет сделать довольно быстро.
-------------------- Вежливым и адекватным предлагаю общаться на "ты". |
|||
|
||||
AndreyIQ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 185 Регистрация: 5.2.2007 Репутация: нет Всего: 8 |
Начиная с Delphi 2009 (если не ошибаюсь) появилась поддержка дженериков. Очень удобно в использовании.
|
|||
|
||||
Чучмек |
|
||||
НЭТ БИЛЭТ ![]() ![]() Профиль Группа: Участник Сообщений: 841 Регистрация: 11.5.2008 Где: СССР Репутация: 14 Всего: 41 |
Почему?
-------------------- умную мысль держи при себе, а дурной - поделись с другими |
||||
|
|||||
CynicRus |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 248 Регистрация: 31.5.2012 Репутация: нет Всего: 5 |
Вот кусочек кода библиотеки Fundamentals, содержит функции для работы с динамическими массивами. Правда автор использовал не указанный выше механизм, а перегрузку функций.
|
|||
|
||||
EKoshelev |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 509 Регистрация: 1.9.2004 Репутация: нет Всего: нет |
AndreyIQ, Спасибо. Не знал. Можно будет глянуть.
Чучмек, CynicRus, Ребята, ну вы предлагаете рассматривать массивы с элементами известных типов. Мне бы хотелось уметь работать с массивами элементов любых типов. Даже неизвестных заранее. На сколько я сумел выяснить на данный момент, динамический массив - это некая структура. Если у нас есть массив Arr: array of SmthType, то Pointer(Arr) указывает на первый (или нулевой) элемент массива integer(Pointer(Arr - 4)) хранит ссылку на переменную с к-вом элементов массива integer(Pointer(Arr - 12)) хранит ссылку на к-во байтов занимаемое массивом минус четырнадцать. Т. е. из двух последних значений можно получить sizeof элемента массива (SizeOf(SmthType)). Короче, для изменения длины массива, вероятно, нужно как-то изменить эту структуру. И вот хотелось бы знать как. -------------------- Вежливым и адекватным предлагаю общаться на "ты". |
|||
|
||||
EKoshelev |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 509 Регистрация: 1.9.2004 Репутация: нет Всего: нет |
Короче, зная о структуре то, что уже я знаю изменение длины массива можно (казалось бы) сделать так:
1. Создать при помощи GetMem фрагмент памяти нужной длины. 2. Перенаправить на него Pointer хранящийся по адресу Pointer(Arr) 3. Изменить длину в ячейке Pointer(Arr - 4); 4. Изменить длину в ячейке Pointer(Arr - 12); 5. И (!) освободить старый массив (FreeMem). Вот на пятом пункте вылетает ошибка: "Invalid pointer operation". -------------------- Вежливым и адекватным предлагаю общаться на "ты". |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 31 Всего: 88 |
а что ты отдаешь во FreeMem? память выделяется одни махом и на сам массив и на служебную информацию, соответственно освобождать нужно так же. Еще прими во внимание что никто тебе не обещал что структура по отрицательному смещению от нулевого элемента будет стабильной между версиями дельфи (например с некоторых пор там есть счетчик ссылок как у строк, хотя раньше небыло).
При таких исследованиях сильно помогает чтение исходников юнита System (ну и прочих внутренностей rtl), ты это делал? И вообще, юзай дженерики и не занимайся извращениями. Особенно это имеет смысл если ты вспомнишь что не все типы элемента можно удалить просто перезаписав их чем-то (например строки, интерфейсы и другие динамические массивы) Это сообщение отредактировал(а) bems - 22.3.2013, 08:39 -------------------- Обижено школьников: 8 |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 31 Всего: 88 |
щас посмотрел system.pas от ХЕ2 и увидел что вот это
неправильно на х64 Arr - 12 используется просто для выравнивания, а на х32 служебная структура динамического массива занимает всего 8 байт (два четырехбайтовых целых Arr - 4 и Arr - 8) Если ты действительно увидел что по смещению -12 лежит поинтер на длину в байтах, то вероятно это служебные данные менеджера памяти, и относятся они не к самому массиву, а к блоку памяти, как его знает менеджер. Короч не нужно освобождать 12 байт перед массивом, нужно 8 Добавлено через 9 минут и 27 секунд И кстати если ты говоришь именно про освобождение, то (по крайней мере в ХЕ2) процедура DynArrayClear доступна для прямого вызова из твоего кода. Это сообщение отредактировал(а) bems - 22.3.2013, 09:00 -------------------- Обижено школьников: 8 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "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. |