Уничтожение значений-объектов массива TMap из FCL-STL

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение java73 » 31.03.2017 13:58:47

Добрый день.
Сделал ассоциированный массив на дженериках, используя TMap из пакета fcl-stl:
Код: Выделить всё
TMapElement = class
    Key: string;
    KeyType: string;
    Value: string;
    constructor Create(_key, _keytype, _value: string);
  end;

  less = specialize TLess<string>;
  TTagsMap = specialize TMap<string, TMapElement, less>;


В другом классе TJHTMLParse есть поле
Код: Выделить всё
fValues: TTagsMap;


В деструкторе главного объекта вызываю метод освобождения памяти ассоциированного массива:
Код: Выделить всё
destructor TJHTMLParse.Destroy;
begin
  fValues.Destroy;
  if Assigned(HTMLFile) then
    HTMLFile.Free;
  inherited;
end;


Модуль работает как надо, но при закрытии heaptrace показывает, что объекты не освободили память. Как правильно поступать с объектами-значениями массива, и могут ли они вообще быть элементами массива TMap?
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение serbod » 31.03.2017 14:17:40

Назначь элементам владельца (TCollection, TOBjectList, TComponent). Или напиши потомка TMap, который умеет быть владельцем.
Аватара пользователя
serbod
постоялец
 
Сообщения: 449
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение zub » 31.03.2017 14:21:25

Код: Выделить всё
TMapElement = record
    Key: string;
    KeyType: string;
    Value: string;
  end;

в данном случае будет гораздо правильней.

>>Назначь элементам владельца (TCollection, TOBjectList, TComponent). Или напиши потомка TMap, который умеет быть владельцем.
vcl голоного мозга?
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение serbod » 31.03.2017 15:00:47

zub писал(а):vcl голоного мозга?

Нет, мозоль от ударов граблями. У record тоже должен быть владелец - обычно это array.
Аватара пользователя
serbod
постоялец
 
Сообщения: 449
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение zub » 31.03.2017 15:15:39

>>Нет, мозоль от ударов граблями. У record тоже должен быть владелец - обычно это array.
а тут будет необычно, тут "владельцем" будет tmap

>>У record тоже должен быть владелец - обычно это array.
всетаки vclгм))
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение java73 » 31.03.2017 15:36:16

Ладно, скажу, почему я сразу в записи не поставил структуру, а хотел класс:
Код: Выделить всё
procedure TJHTMLParse.PutValue(_key, _Value: string);
var E: TMapElement;
begin
  E:=Values[(RDelim + _key + LDelim)];
  E.Value:=_Value;
  Values[(RDelim + _key + LDelim)] := E;
end;

Вот нельзя просто написать Values[key].Value := X;
потому что сразу error argument cannot be assigned to
А при объекте можно было прописать Values[key].Value := X
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение zub » 31.03.2017 15:43:21

При каком объекте? object это совсем не класс и в общем случае уже не рекорд.
Давайка мил челове нормальные компилируемые примеры, а не выдирки непойми чего

>>Ладно, скажу, почему я сразу в записи не поставил структуру, а хотел класс:
в данном контексте "не поставил структуру" - какраз нужно поставить.
argument cannot be assigned to - совсем не поэтому
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение java73 » 31.03.2017 15:50:25

zub писал(а):Давайка мил челове нормальные компилируемые примеры, а не выдирки непойми чего

Даю.
1. Элемент массива - объект (см. реализацию метода PutValue ближе к концу)

2. Элемент массива - запись. Реализация PutValue подросла.

Добавлено спустя 4 минуты 16 секунд:
Под понятием "объект" я выше, здесь и далее подразумеваю экземпляр класса.
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение zub » 31.03.2017 15:57:47

>>Даю.
Не беру. давай ятоб влазило в сообщения форума. напроимер:
Код: Выделить всё
program Project1;
uses
  gmap,gutil;
type
TMapElement = record
    Key: string;
    KeyType: string;
    Value: string;
  end;

  less = specialize TLess<string>;
  TTagsMap = specialize TMap<string, TMapElement, less>;
function TMapElement_Create(_key, _keytype, _value: string):TMapElement;
begin
  result.Key:=_key;
  result.KeyType:=_keytype;
  result.Value:=_value;
end;
var
  m:TTagsMap;
begin
  m:=TTagsMap.Create;
  m.Insert('1',TMapElement_Create('1','2','3'));
  m.Insert('2',TMapElement_Create('1','2','3'));
  m.Destroy;
end.
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение java73 » 31.03.2017 16:25:21

Вот, возвращаясь к прошлой теме, в DeCAL-то устроено все именно с точки зрения удаления объектов проще - ObjFree(DMap) и всё. Но чуть сложнее присвоение и получение значений (сложнее для чтения кода). Тут проще, но не настолько, как я думал.
Хотелось бы, чтоб
а) присвоение - Map[key]:=value (это работает, но если key есть, то значение перезапишется просто, а key нет, то добавится) вместо Insert
б) изменение Map[key].Name:=newname, а не сначала полностью получить всю запись value, в ней поменять поле name, и потом поместить обратно всю запись value в map.
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение serbod » 31.03.2017 16:48:41

java73 писал(а):изменение Map[key].Name := newname

Что будет, если Map[key] вернет nil? А оно обязательно будет.

Если не хочется заморачиваться с назначением владельца создаваемых объектов, то можно заморочиться с использованием интерфейсов вместо классов, они автоматически удаляются при отсутствии ссылок на них. Главная фишка - ссылка должна быть типа IInterface, а не TObject, иначе работать не будет.

Добавлено спустя 6 минут 30 секунд:
Совсем правильно было бы сделать так:
Код: Выделить всё
TTagsMap.SetItemName(const AKey, AName: string): Boolean;
var
  TmpItem: TMapElement;
begin
  Result := False;
  TmpItem := Map[AKey];
  if Assigned(TmpItem) and (TmpItem.Name <> AName) then
  begin
    TmpItem.Name := AName;
    Result := True;
  end;
end;
Аватара пользователя
serbod
постоялец
 
Сообщения: 449
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение Снег Север » 31.03.2017 17:08:50

Ребята, простите, но вы тут что-то полную фигню написали.
Во-первых, топикстартер действительно может использовать рекорды, в них уже давненько можно писать свои процедуры типа Init, если надо делать инициализацию. Рекорды еще хороши тем, что для них можно написать переопределения операторов действий.
Во-вторых, у классов никаких "владельцев" не бывает, это не компоненты. Если топикстартер хочет использовать классы как элементы, то перед удалением массива ему надо просто пробежаться по массиву с вызовом Freeandnil для каждого элемента. Так, как это делается в кувырсотнадцати других паскалевских модулях.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение java73 » 31.03.2017 17:54:28

serbod писал(а):Что будет, если Map[key] вернет nil? А оно обязательно будет

Зачем это будет?
Если key новый, то создастся новый элемент массива, вот и всё.

Снег Север писал(а): ему надо просто пробежаться по массиву с вызовом Freeandnil для каждого элемента

Остановился на использовании записей, ладно.
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение Снег Север » 31.03.2017 18:03:26

java73, тут, конечно нет какого-то закона, но из практики я себе выработал следующий принцип - если нужна просто структура хранения данных с минимумом внутренних обработок, то использовать рекорды, если предполагается поведение и/или наследование - использовать классы.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Уничтожение значений-объектов массива TMap из FCL-STL

Сообщение serbod » 31.03.2017 18:49:13

Снег Север, record хороши только гарантированным порядком элементов и возможностью выравнивания по размеру, что ценно во всяких API и бинарных форматах данных. Для чисто внутреннего пользования классы гораздо предпочтительнее. Рано или поздно придется делать всякие инициализации-валидации-добавления-удаления и прочие фокусы.
Аватара пользователя
serbod
постоялец
 
Сообщения: 449
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23

Рейтинг@Mail.ru