Object creation not assigned to variable

90 views Asked by At

I'd like to use a method of a class without assigning its creation to a variable. For example:

type
  TMyObject = class
  public
    procedure DoSomething;
  end;

implementation

procedure MyObjDoesSomething;
begin
  TMyObject.Create.DoSomething;
end;

{ TMyObject }

procedure TMyObject.DoSomething;
begin
  // ...
end;

As you can see, in MyObjDoesSomething I didn't assign TMyObject.Create to a TMyObject variable.

Does this have some kind of impact on memory usage, or even something else I did't think of?

2

There are 2 answers

6
Remy Lebeau On

If you Create an object to allocate memory for it, you must call Free() on the object when you are done using it to release that memory, otherwise the memory is leaked, which will impact memory over time if you create these objects multiple times.

If you don't want to use an explicit variable to refer to the object (why?), you can use a with block, eg:

procedure MyObjDoesSomething;
begin
  with TMyObject.Create do
  try
    DoSomething;
  finally
    Free;
  end;
end;

Another option is to make the class implement an interface, and then you can let the compiler's reference counting of interfaces handle freeing the object for you. This has a little bit more overhead than above, but you don't have to worry as much about handling the memory manually, eg:

type
  IMyObject = interface
    ['{896FF4FA-A974-4A8B-9EA5-414C138635E4}']
    procedure DoSomething;
  end;

  TMyObject = class(TInterfacedObject, IMyObject)
  public
    procedure DoSomething;
  end;

implementation

procedure MyObjDoesSomething;
begin
  (TMyObject.Create as IMyObject).DoSomething;
end;

{ TMyObject }

procedure TMyObject.DoSomething;
begin
  // ...
end;

But really, just use a variable instead. It costs you nothing to use:

procedure MyObjDoesSomething;
var
  Obj;
begin
  Obj := TMyObject.Create;
  try
    Obj.DoSomething;
  finally
    Obj.Free;
  end;
end;
0
fpiette On

Yes, there is a big impact: A nice memory leak!

You call the constructor of an object but never free the created object. Each time you'll call your MyObjDoesSomething, you'll leak an object instance.

To solve that problem, you could make a class method of DoSomething like this:

type
  TMyObject = class
  public
    class procedure DoSomething;
  end;

Then you can call DoSomething without creating an object like this:

procedure MyObjDoesSomething;
begin
  TMyObject.DoSomething;
end;

Being a class method, DoSomething implementation cannot use object instance variables (fields).