![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TList & records [D7, XP]
_Андрей © (2009-08-07 12:14:00)Здравствуйте.
Для хранения списка таких вот записей:
type
PRasEntry = ^TRasEntry;
TRasEntry = record
Name, User, Pswd, Phone: string;
end;
создал наследника TList:
type TRasList = class(TList)
private
function ReadItem(index: integer): TRasEntry;
procedure WriteItem(index: integer; const Value: TRasEntry);
public
procedure AddItem(RasEntry: TRasEntry); overload;
procedure AddItem(Name, User, Pswd, Phone: string); overload;
property RasItems[index: integer]: TRasEntry read ReadItem write WriteItem;
destructor Destroy; override;
end;
Вот его реализация:
procedure TRasList.AddItem(RasEntry: TRasEntry);
var P: PRasEntry;
begin
New(P);
P^ := RasEntry;
Add(P)
end;
procedure TRasList.AddItem(Name, User, Pswd, Phone: string);
var P: PRasEntry;
begin
New(P);
P^.Name := Name; P^.User := User; P^.Pswd := Pswd; P^.Phone := Phone;
Add(P)
end;
function TRasList.ReadItem(index: integer): TRasEntry;
begin
if (index >=0) and (index <= Count-1) then Result := TRasEntry(Items[index]^)
end;
procedure TRasList.WriteItem(index: integer; const Value: TRasEntry);
begin
if (index >=0) and (index <= Count-1) then
begin
TRasEntry(Items[index]^).Name := Value.Name;
TRasEntry(Items[index]^).User := Value.User;
TRasEntry(Items[index]^).Pswd := Value.Pswd;
TRasEntry(Items[index]^).Phone := Value.Phone
end
end;
destructor TRasList.Destroy;
var i: integer;
begin
for i:=Count-1 downto 0 do
begin
Dispose(Items[i]);
Delete(i)
end;
inherited
end;
Проблема в том что FastMM при добавлении каких-либо элементов в список находит в этом коде утечки памяти, подскажите, плиз, что не так делаю, может у кого-нить есть пример хранения записей в списке...
Игорь Шевченко (2009-08-07 16:30:00) [1]Kolan © (07.08.09 15:49) [30]
RTFS: db.pas TLookupList
Не сделали классом. Ибо нефиг
Kolan (2009-08-07 15:49:00) [2]Игор, я помню про то, что такие классы, без инкапсуляции, лучше не делать. Но. 1. Запись не лучше.
2. Для записи, в данном случае, приходится городить огород с удалением и прочим, а с классами такой проблемы нет.
То есть я думаю, что в сабже можно сделать рефакторинг в два этапа. На первом этапе просто заменить запись на класс и избавиться от геморроя с указателями и памятью. А когда автору понадобится модифицировать класс (если понадобится), он сделает нормальную инкапсуляцию, заменив поля одноименными свойствами.
То есть с классом у него сейчас будет меньше трудностей, а в будущем больше возможностей.
Игорь Шевченко (2009-08-07 15:13:00) [3]Kolan © (07.08.09 14:00) [24]
Ты ж Фаулера учил, который пишет, что от таких классов надо избавляться ? А сам рекомендуешь, как же так ? :)
DVM (2009-08-07 15:12:00) [4]
> TRasEntry = class
> public
> Name, User, Pswd, Phone: string;
> end;
В таких классах нет смысла. Класс ради класса.
MsGuns (2009-08-07 14:58:00) [5]>Kolan © (07.08.09 14:00) [24]
Действительно:)
А я ж думал с пропертями вместо простых переменных, конструкторами-деструкторами :)
Юрий Зотов (2009-08-07 14:11:00) [6]> _Андрей (07.08.09 13:48) [19]
Не нужно ничего добавлять, только код загромождаться будет. Уберите деструктор и заместите Notify, вот и все. А еще лучше - прислушаться к советам и использовать класс вместо записи, так проще и безопаснее.
Юрий Зотов (2009-08-07 14:07:00) [7]> MsGuns © (07.08.09 13:56) [23]
[24] загромождает код куда меньше, чем [0]. Потому что не требует ни единой строчки дополнительного кода.
Kolan (2009-08-07 14:00:00) [8]MsGuns, вы про такое загромождение?
TRasEntry = class
public
Name, User, Pswd, Phone: string;
end;
MsGuns (2009-08-07 13:56:00) [9]>Kolan © (07.08.09 13:50) [20]
Потому что для простых объектов-записей (типа сабжа) писАть классы - только загромождать код
MsGuns (2009-08-07 13:54:00) [10]> Best of the best (07.08.09 13:29) [16]
А почему бы не так:
while Count>0 do
begin
Dispose(PRasEntry(Items[0]);
Delete(0);
end;
inherited
Kolan (2009-08-07 13:52:00) [11]Да, а не счет того, что этот набор данных не достоин стать объектом из-за того, что он слишком прост, то стоит только сделать объект, как найдутся методы, которые удобно поместить именно в нем. Про это рассказывается в книге Мартина Фаулера «Рефакторинг».
Kolan (2009-08-07 13:50:00) [12]Я об обычных объектах, которые наследники
TObject.
То есть почему бы не написать так:
TRasEntry = class
...
и не использоватьTObjectList?
_Андрей (2009-08-07 13:48:00) [13]
> Юрий Зотов © (07.08.09 13:39) [18]
Имеется ввиду Delete и Remove класса TList, да?
То есть нужно, например, добавить функцию:
> TRasList.RasDelete(Index: integer);
> begin
> Dispose(PRasEntry(Items(Index)));
> Delete(Index)
> end
Хотя вариант лучшего "покруче" будет...
Юрий Зотов (2009-08-07 13:39:00) [14]> _Андрей
Кстати, в [16] дело сказано. Иначе будет неверно работать удаление из списка (Delete и Remove).
Anatoly Podgoretsky (2009-08-07 13:31:00) [15]> _Андрей (07.08.2009 13:03:07) [7]
Знание, что это указатель на TRasEntry и что его надо финализировать.
Best of the best (2009-08-07 13:29:00) [16]
>destructor TRasList.Destroy;
> var i: integer;
> begin
> for i:=Count-1 downto 0 do
> begin
> Dispose(Items[i]);
> Delete(i)
> end;
> inherited
> end;
>
Вместо вышеописанного правильнее будет перекрыть метод Notify:
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
procedure TRasList.Notify(Ptr: Pointer; Action: TListNotification);
begin
case Action of
lnDeleted: Dispose(PRasEntry(Ptr));
end;
end;
Юрий Зотов (2009-08-07 13:28:00) [17]> _Андрей (07.08.09 13:20) [12]
Длиные строки Delphi - это указатели. Поэтому Ваша запись содержит 4 указателя и занимает 16 байт, независимо от длины ее строк. Сами же строки (то есть, их тела) хранятся в другом месте.
Юрий Зотов (2009-08-07 13:24:00) [18]> _Андрей (07.08.09 13:20) [12]
Освобождает память, занятую записью, но не освобождает память, занятую строками этой записи (name и пр.).
MBo (2009-08-07 13:23:00) [19]Dispose(Items[i]) передается нетипизированный указатель, и про него системе известно только то, что по этому адресу выделено 16 байт
_Андрей (2009-08-07 13:20:00) [20]
> MBo © (07.08.09 13:15) [10]
А что тогда делает:
Dispose(Items[i])
Осовбождает только часть или вообще ничего?