Compiler Attributes

From RAD Studio
Jump to: navigation, search

Go Up to Attributes (RTTI)


Some special attributes trigger certain features of Delphi compilers.

Ref

The Ref attribute is used to qualify constant function parameters so that they are passed by reference (not by value) to the function. For more information, see Constant Parameters.

Volatile

The volatile attribute is used to mark fields that are subject to change by different threads, so that code generation does not optimize copying the value in a register or another temporary memory location.

You can use the volatile attribute to mark the following declarations:

You cannot use the volatile attribute to mark the following declarations:

type
    TMyClass = class
    private
        [volatile] FMyVariable: TMyType;
    end;

Weak and Unsafe Attributes

Note: The use of weak and unsafe references was originally introduced as part of the ARC memory management support for mobile platforms. As ARC is now phased out, this feature remains available only for interface references.

Weak

Weak is an interface reference that does not increase the reference count of the object they refer to. It is marked with the [weak] modifier. This feature is only supported by Delphi. You can use weak references in the following cases:

  • To avoid increasing count references.
  • To manage interface references. This means that the system keeps track of them when the actual object is deleted.
Note: As weak references are fully managed, they are automatically set to nil if the referenced object is destroyed.
  • To break the circular references between two objects with cross-references. When this happens, you end up with a memory leak.

As an example, consider the following interface accepting a reference to another interface of the same type, and a class implementing it with an internal reference:

type
  ISimpleInterface = interface 
  procedure DoSomething; 
  procedure AddObjectRef(Simple: ISimpleInterface); 
 end; 
 TObjectOne = class(TInterfacedObject, ISimpleInterface)
 private 
  AnotherObj: ISimpleInterface; 
 public 
  procedure DoSomething; 
  procedure AddObjectRef(Simple: ISimpleInterface); 
 end;

If you create two objects and cross-reference them, you end up with a memory leak:

var 
 One, Two: ISimpleInterface; 
begin 
  One := TObjectOne.Create; 
  Two := TObjectOne.Create;
  One.AddObjectRef(Two); 
  Two.AddObjectRef(One);

Now the solution available in Delphi is to mark the private field AnotherObj as a weak interface reference:

private 
  [weak] AnotherObj: ISimpleInterface;

With this change, the reference count is not modified when you pass the object as a parameter to the AddObjectRef call, it stays at 1, and it goes back to zero when the variables go out of scope, freeing the objects from memory.

Note: You can only pass a [weak] variable to a var or out parameter marked as [weak]. You cannot pass a regular strong reference to a [weak] var or out parameter.

Unsafe

An Unsafe reference is an interface reference that does not increase the reference count of the object they refer to. It is marked with the [unsafe] modifier.

Note: Unsafe references are not managed, similar to a pointer with no extra compiler support.

You can use unsafe when you want to create an interface reference that is kept out of the total count of references. For example:

procedure TForm3.Button2Click(Sender: TObject); 
var 
 [unsafe] OneIntf: ISimpleInterface;
begin 
 OneIntf := TObjectOne.Create; 
 OneIntf.DoSomething; 
end;
Note: You can only pass a [Unsafe] variable to a var or out parameter that is also marked as [Unsafe]. You cannot pass a regular strong reference to a [Unsafe] var or out.

See Also