![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Снова проблемы (вырезка элементов массива)
ProgRAMmer Dimonych © (2007-09-15 14:45:00)Имеется массив record'ов, причём в описании record'а входит одно поле-объект. Т.е. что-то типа
TMyObjectClass=class(TObject)
private
...
public
...
end;
TMyRec=record
Something1:Integer;
Something2:Boolean;
SomeObject:TMyObjectClass;
end;
TMyRecArray=array of TMyRec;
Этот массив в свою очередь является полем другого объекта. И в этом большом объекте есть методы для добавления элементов в конец массива и для удаления заданного элемента. Собственно, последний метод у меня и вызывает проблемы.
Стоит задача: после вырезания (удаления) указанного элемента массива все остальные сместить, т.е., например, при удалении 0-го элемент из массива
A[0]=...
A[1]=...
Должен остаться только A[0], полученный в результате его перемещения к началу массива.
Использую такой код:
procedure TLesson.RemoveEl(ID:Integer);
var
i,L:Integer;
begin
L:=Length(FArray)-1;
if L<>-1 then
begin
for i:=ID+1 to L do FArray[i-1]:=FArray[i];
end;
FPages[L].SomeObject.Free;
SetLength(FPages,L);
end;
Удаление вроде как происходит, но при попытке обратиться к SomeObject (наследнику TObject) за нумером 0 вылетает AV.
Как всё-таки правильно здесь выполнить эту операцию?
Вася Правильный (2007-09-16 21:06:00) [1]
> Denis_ © (16.09.07 17:51) [9]
я не обсираюсь
ProgRAMmer Dimonych (2007-09-16 20:01:00) [2]> Denis_ © (16.09.07 17:51) [9]
> > поздно подтираться, когда обосрался
> > а пока прога в релиз не пошла, не поздно
> А что, Вы подтираетесь до того как...?
:)
Denis_ (2007-09-16 17:51:00) [3]
> поздно подтираться, когда обосрался
> а пока прога в релиз не пошла, не поздно
А что, Вы подтираетесь дотого как...?
Вася Правильный (2007-09-16 17:44:00) [4]
> Поздно :(
поздно подтираться, когда обосрался
а пока прога в релиз не пошла, не поздно
Loginov Dmitry (2007-09-16 11:36:00) [5]> Имеется массив record'ов, причём в описании record'а входит
> одно поле-объект
При появлении подобных ситуаций всегда переправляю recordна class, а array ofна TList. После этого испорченная логика встает на место.
ProgRAMmer Dimonych (2007-09-15 22:10:00) [6]> Вася Правильный (15.09.07 21:05) [5]
> > TMyRecArray=array of TMyRec;
> замени на TList, пока не поздно
Поздно :(
Вася Правильный (2007-09-15 21:05:00) [7]
> TMyRecArray=array of TMyRec;
замени на TList, пока не поздно
ProgRAMmer Dimonych (2007-09-15 20:36:00) [8]> Плохиш © (15.09.07 15:14) [3]
> Из логики вытекает. Сам смотри. Если сначала перезапишешь
> ссылку на объект, то как ты его потом удалять будешь. Ссылка-
> то потеряна...
> А в твоём коде удаляется объект в последнем элементе массива,
> тебе просто повезло, что элементов было всего 2 и ты сразу
> получил исключение :-) представляешь, что при паре миллионов
> элементов, исключение возникло бы месяца через три, как
> бы ты её искать стал ;-)
Прочитал, подумал, сообразил. Спасибо ещё раз.
Плохиш (2007-09-15 15:14:00) [9]
> Но идею понял: сначала удаляем объект из удаляемого record'а,
> потом выполняем перезапись всего остального.
Из логики вытекает. Сам смотри. Если сначала перезапишешь ссылку на объект, то как ты его потом удалять будешь. Ссылка-то потеряна...
А в твоём коде удаляется объект в последнем элементе массива, тебе просто повезло, что элементов было всего 2 и ты сразу получил исключение :-) представляешь, что при паре миллионов элементов, исключение возникло бы месяца через три, как бы ты её искать стал ;-)
ProgRAMmer Dimonych (2007-09-15 15:06:00) [10]> Плохиш © (15.09.07 14:51) [1]
Как всегда, чтобы завуалировать реальное назначение программы и сделать вопрос более общим, позаменял названия переменных и проч., но как всегда не все :(
Но идею понял: сначала удаляем объект из удаляемого record'а, потом выполняем перезапись всего остального. Работает. Правда, честно говоря, не смог с ходу вникнуть в суть происходящего, так что буду благодарен небольшому пояснению.
А в целом уже огромное спасибо.
Плохиш (2007-09-15 14:51:00) [11]
procedure TLesson.RemoveEl(ID:Integer);
var
i,L:Integer;
begin
L:=Length(FArray)-1;
if L<>-1 then
begin
FPages[ID].SomeObject.Free;
for i:=ID+1 to L do FArray[i-1]:=FArray[i];
end;
SetLength(FPages,L);
end;