![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создать несколько экз. класса сразу.
Димка На © (2012-03-11 16:20:00)Нужно к примеру создать 1000 экземпляров класса TMyClass, можно ли нормальным способом 1 раз выделить под это память и затем инициализировать каждый объект? Если да, то как?
PS. Интересуют более менее нормальные способы.
asdawert (2012-03-12 23:47:00) [1]
> oxffff © (12.03.12 00:24) [11]
Месье знает толк в извращениях ;)
Inovet (2012-03-12 20:47:00) [2]> [13] Cobalt © (12.03.12 14:24)
> А какова выгода от сего действия?
Для каких-то специфических данных без динамического распределения памяти под их элементы, может и лучше.
Cobalt (2012-03-12 14:24:00) [3]А какова выгода от сего действия?
oxffff (2012-03-12 00:30:00) [4]Если нужно конструктор с параметрами, то можно добавить анонимный метод инициализатор, который дергает нужный конструктор
oxffff (2012-03-12 00:24:00) [5]Готово.
Усовершенствованная версия. :)
TStuff<T:class,constructor>=class(TInterfacedObject,TFunc<integer,T>)
protected
Block:pointer;
public
function Invoke(idx:integer):T;
constructor create(Count:integer);
destructor destroy;override;
end;
TDemo=class
procedure Demo;
end;
function TForm1.Alloc<T>(Count:integer):TFunc<integer,T>;
begin
result:=TStuff<T>.create(Count);
end;
procedure TForm1.FormCreate(Sender: TObject);
var func:TFunc<integer,TDemo>;
begin
func:=Alloc<TDemo>(100);
func(0).Demo;
func(1).Demo;
func(2).Demo;
func:=nil;// by by memory block
end;
{ TStuff<T> }
constructor TStuff<T>.create(Count: integer);
var p:pointer;
i:integer;
obj:T;
begin
Getmem(Block,T.InstanceSize*Count);
ZeroMemory(Block,T.InstanceSize*Count);
p:=Block;
for i:=1 to Count do
begin
T.InitInstance(p);
obj:=T(Tobject(p));
obj.create();
//obj.AfterConstruction; <- вызовится в конструкторе поскольку dl = -1
inc(pbyte(p),T.InstanceSize);
end;
end;
destructor TStuff<T>.destroy;
begin
FreeMem(Block);
inherited;
end;
function TStuff<T>.Invoke(idx: integer): T;
var p:pointer;
begin
p:=Block;
inc(pbyte(p),T.InstanceSize*idx);
result:=T(Tobject(p));
end;
{ TDemo }
procedure TDemo.Demo;
begin
showmessage('Instance of '+ClassName+' at '+inttostr(integer(Self)));
end;
oxffff (2012-03-12 00:09:00) [6]oxffff © (12.03.12 00:07) [9]
Сейчас попробую вкусность обернуть еще лучше.
Потом спать, утром как обычно ABAP, JAVA, JAVASCRIPT.
oxffff (2012-03-12 00:07:00) [7]Набросок
function TForm1.Alloc<T>(Count:integer):T;
var p:pointer;
i:integer;
obj:T;
begin
Getmem(p,T.InstanceSize*Count);
ZeroMemory(p,T.InstanceSize*Count);
for i:=1 to Count do
begin
T.InitInstance(p);
obj:=T(Tobject(p));
obj.create();
//obj.AfterConstruction; <- вызовится в конструкторе поскольку dl = -1
inc(pbyte(p),T.InstanceSize);
end;
end;
Пример
Alloc<TPersistent>(100);
Anatoly Podgoretsky (2012-03-11 19:34:00) [8]Это не строки, здесь выигрыша нет
CRLF (2012-03-11 19:15:00) [9]
> и будет 1000 выделений памяти..
А даже если выделишь память один раз, конструкторы вызывать придётся тысячу раз. Есть мнение, что не там ты оптимизируешь.
Jeer (2012-03-11 17:46:00) [10]Если в объектах нет "динамики" - можно, если есть - глупая затея.
Димка На (2012-03-11 17:32:00) [11]
> list := TMyClassList.create;
> for i := 0 to 999 do
> list.AddMyObject;
>
и будет 1000 выделений памяти..
Вопрос не в том как на них ссылки деражть, а как не выделять 100500 раз память, а разом.
Ega23 (2012-03-11 17:26:00) [12]И не надо изобретать велосипед.
Ega23 (2012-03-11 17:25:00) [13]
> Нужно к примеру создать 1000 экземпляров класса TMyClass,
uses Contnrs;
TMyClassList = class (TObjectList)
private
function GetItem(Index: Integer): TMyClass;
public
function AddMyObject: TMyClass;
property Items[Index: Integer]: TMyClass read GetItem; default;
end;
function TMyClassList.AddMyObject: TMyClass;
begin
Result := TMyClass.Create;
Add(Result);
end;
function TMyClassList.GetItem(Index: Integer): TMyClass;
begin
Result := TMyClassL(inherited GetItem(Index));
end;
list := TMyClassList.create;
for i := 0 to 999 do
list.AddMyObject;
Dimka Maslov (2012-03-11 16:59:00) [14]
> icWasya © (11.03.12 16:40) [1]
только надо бы
Result := InitInstance(@MyClassMemory[MyClassLastIndex]);
и не забыть всю эту память где-нибудь грохануть.
icWasya (2012-03-11 16:40:00) [15]Можно переопределить классовые методы NewInstance и FreeInstance
Например так
procedure InitMyClassMemory(ClassCount:Integer);
type
TMyClass = class
class function NewInstance:TObject; override;
class procedure FreeInstance; override;
class procedure InitMemory(ClassCount:Integer);
end;
implementation
Var
MyClassMemory:Array of Byte; // это память под класс
MyClassLastIndex:Integer;// количество созданых экземпляров
// инициализируем память
class procedure TMyClass.InitMemory(ClassCount:Integer);
begin
MyClassLastIndex:=0;
SetLength(MyClassMemory,ClassCount*InstanceSize);
end;
// вместо выделения памяти
class function TMyClass.NewInstance:TObject;
begin
Result:=TObject(@MyClassMemory[MyClassLastIndex]);
MyClassLastIndex:=MyClassLastIndex+InstanceSize;
end;
// вместо освобождения памяти
class procedure TMyClass.FreeInstance;
begin
Exit;
end;
initialization
TMyClass.InitMemory(1000);
Контроль за наличием инициализации и выход за границу массива - по вкусу.
Далее делаем обычный TMyClass.Create - и память будет выделяться из массива MyClassMemory.