# Objects

An object in AutoHotkey is an abstract data structure which provides three basic functions:

- GET a value.
- SET a value.
- CALL a method (that is, a function which does something with the target object).

An object reference is a pointer or "handle" to a particular object. Like strings and numbers, object references can be stored in variables, passed to or returned from functions and stored in objects. After copying a reference from one variable to another as in `x := y`, both variables refer to the same object.

IsObject can be used to determine if a value is an object:

    Result := IsObject(expression)

Types of objects include:

- Object - scriptable associative array.
- File - provides an interface for file input/output.
- Func - a function.
- ComObject - wraps an IDispatch interface (a COM or "Automation" object).

## Table of Contents

- Basic Usage - Simple Arrays, Associative Arrays, Objects, Freeing Objects, Remarks
- Extended Usage - Function References, Arrays of Arrays, Arrays of Functions
- Custom Objects - Prototypes, Classes, Construction and Destruction, Meta-Functions
- Default Base Object - Automatic Var Init, Pseudo-Properties, Debugging
- Implementation - Reference-Counting, Pointers to Objects

## Basic Usage

### Simple Arrays

Create an array:

    Array := [Item1, Item2, ..., ItemN]
    Array := Array(Item1, Item2, ..., ItemN)

Retrieve an item:

    Value := Array[Index]

Assign an item:

    Array[Index] := Value

Append an item:

    Array.Insert(Value)

Insert one or more items at a given index:

    Array.Insert(Index, Value, Value2, ...)

Remove an item:

    RemovedValue := Array.Remove(Index)

If the array is not empty, MinIndex and MaxIndex return the lowest and highest index currently in use in the array. Since the lowest index is nearly always 1, MaxIndex usually returns the number of items. Looping through an array's contents can be done either by index or with a For-loop. For example:

    array := ["one", "two", "three"]

    ; Iterate from 1 to the number of items:
    Loop % array.MaxIndex()
        MsgBox % array[A_Index]

    ; Enumerate the array's contents:
    For index, value in array
        MsgBox % "Item " index " is '" value "'"

### Associative Arrays

An associative array is an object which contains a collection of unique keys and a collection of values, where each key is associated with one value. Keys can be strings, integers or objects, while values can be of any type. An associative array can be created as follows:

    Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
    Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)

Using the `{key:value}` notation, quote marks are optional for keys which consist only of word characters. Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, `{(KeyVar): Value}` and `{GetKey(): Value}` are both valid.

Retrieve an item:

    Value := Array[Key]

Assign an item:

    Array[Key] := Value

Remove an item:

    RemovedValue := Array.Remove(Key)

Enumerating items:

    array := {ten: 10, twenty: 20, thirty: 30}
    For key, value in array
        MsgBox %key% = %value%

Associative arrays can be sparsely populated - that is, `{1:"a",1000:"b"}` contains only two key-value pairs, not 1000.

By now, you may have noticed that associative arrays use very similar syntax to simple arrays. In fact, they're both the same thing in v1.x. However, treating `[]` as a simple linear array helps to keep its role clear, and improves the chance of your script working with a future version of AutoHotkey, which might change the implementation.

### Objects

Retrieve a property:

    Value := Object.Property

Set a property:

    Object.Property := Value

Call a method:

    ReturnValue := Object.Method(Parameters)

Call a method with a computed method name:

    ReturnValue := Object[MethodName](Parameters)

Some properties of COM objects and user-defined objects can accept parameters:

    Value := Object.Property[Parameters]
    Object.Property[Parameters] := Value

Related: Object, File Object, Func Object, COM object

Known limitation:

- Currently `x.y[z]()` is treated as `x["y", z]()`, which is not supported. As a workaround, `(x.y)[z]()` evaluates `x.y` first, then uses the result as the target of the method call. Note that `x.y[z].()` does not have this limitation since it is evaluated the same as `(x.y[z]).()`.

### Freeing Objects

Scripts do not free objects explicitly. When the last reference to an object is released, the object is freed automatically. A reference stored in a variable is released automatically when that variable is assigned some other value. For example:

    obj := {}  ; Creates an object.
    obj := ""  ; Releases the last reference, and therefore frees the object.

Similarly, a reference stored in a field of another object is released when that field is assigned some other value or removed from the object. This also applies to arrays, which are actually objects.

    arr := [{}]  ; Creates an array containing an object.
    arr[1] := {}  ; Creates a second object, implicitly freeing the first object.
    arr.Remove(1)  ; Removes and frees the second object.

Because all references to an object must be released before the object can be freed, objects containing circular references aren't freed automatically. For instance, if `x.child` refers to `y` and `y.parent` refers to `x`, clearing `x` and `y` is not sufficient since the parent object still contains a reference to the child and vice versa. To resolve this situation, remove the circular reference.

    x := {}, y := {}             ; Create two objects.
    x.child := y, y.parent := x  ; Create a circular reference.

    y.parent := ""               ; The circular reference must be removed before the objects can be freed.
    x := "", y := ""             ; Without the above line, this would not free the objects.

For more advanced usage and details, see Reference Counting.

### Remarks

#### Syntax

All types of objects support both array syntax (brackets) and object syntax (dots).

Additionally, object references can themselves be used in expressions:

- When an object reference is compared with some other value using one of `= == != <>`, they are considered equal only if both values are references to the same object.
- Objects are always considered true when a boolean value is required, such as in `if obj`, `!obj` or `obj ? x : y`.
- An object's address can be retrieved using the `&`address-of operator. This uniquely identifies the object from the point of its creation to the moment its last reference is released.

If an object is used in any context where an object is not expected, it is treated as an empty string. For example, `MsgBox %object%` shows an empty MsgBox and `object + 1` yields an empty string. Do not rely on this behaviour as it may change.

When a method-call is followed immediately by an assignment operator, it is equivalent to setting a property with parameters. For example, the following are equivalent:

    obj.item(x) := y
    obj.item[x] := y

Compound assignments such as `x.y += 1` and `--arr[1]` are supported.

#### Keys

Some limitations apply to which values can be used as keys in objects created with `[]`, `{}` or the `new` operator:

- Integer keys are stored using the native signed integer type. AutoHotkey 32-bit supports integer keys in the range -2147483648 to 2147483647. AutoHotkey supports 64-bit integers, but only AutoHotkey 64-bit supports the full range as keys in an object.
- As a consequence of the point above, the string format of integer values is not retained. For example, `x[0x10]`, `x[16]` and `x[00016]` are equivalent. This also applies to numeric strings which don't have a decimal point.
- Quoted literal strings are considered purely non-numeric in v1.x, so `x[1]` and `x["1"]` are not equivalent. Additionally, if a quoted literal string is concatenated with another value (as in `"0x" x`), the result is treated as purely non-numeric. However, this does not apply to variables, so `x[1]` and `x[y:="1"]` are equivalent. This issue will be resolved in v2, so scripts should avoid using quoted numeric literals as keys.
- Floating-point numbers are not supported as keys - instead they are converted to strings. In v1.x, floating-point literals retain their original format whereas pure floating-point numbers (such as the result of `0+1.0` or `Sqrt(y)`) are forced into the current float format. For consistency and clarity, scripts should avoid using floating-point literals as keys.
- The string key "base" has special meaning, except when used with Insert.

## Extended Usage

### Function References [v1.1.00+]

If the variable func contains a function name, the function can be called one of two ways: `%func%()` or `func.()`. However, this requires the function name to be resolved each time, which is inefficient if the function is called more than once. To improve performance, the script can retrieve a reference to the function and store it for later use:

    Func := Func("MyFunc")

To call a function by reference, the following syntax must be used:

    RetVal := Func.(Params)

For details about additional properties of function references, see Func Object.

Known limitation:

- Fixed in v1.1.07.00: If the function or a subroutine or function called by it uses Exit, it acts as though the function-call created a new thread. That is, it returns immediately to the caller of the function rather than terminating the current thread. However, Exit still causes the script to terminate if it is not persistent.

### Arrays of Arrays

AutoHotkey supports "multi-dimensional" arrays by transparently storing arrays inside other arrays. For example, a table could be represented as an array of rows, where each row is itself an array of columns. In that case, the content of column `y` of row `x` can be set using either of the methods below:

    table[x][y] := content  ; A
    table[x, y] := content  ; B

If `table[x]` does not exist, A and B differ in two ways:

- A fails whereas B automatically creates an object and stores it in `table[x]`.
- If `table`'s base defines meta-functions, they are invoked as follows:

      table.base.__Get(table, x)[y] := content   ; A
      table.base.__Set(table, x, y, content)     ; B

  Consequently, B allows the object to define custom behaviour for the overall assignment.

Multi-dimensional assignments such as `table[a, b, c, d] := value` are handled as follows:

- If there is only one key remaining, perform the assignment and return. Otherwise:
- Search the object for the first key in the list.
- If a non-object is found, fail.
- If an object is not found, create one and store it.
- Recursively invoke the sub-object, passing the remaining keys and value - repeat from the top.

This behaviour only applies to script-created objects, not more specialized types of objects such as COM objects or COM arrays.

### Arrays of Functions

An array of functions is simply an array containing function names or references. For example:

    array := [Func("FirstFunc"), Func("SecondFunc")]

    ; Call each function, passing "foo" as a parameter:
    Loop 2
        array[A_Index].("foo")

    ; Call each function, implicitly passing the array itself as a parameter:
    Loop 2
        array[A_Index]()

    FirstFunc(param) {
        MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
    }
    SecondFunc(param) {
        MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)
    }

For backward-compatibility, the second form will not pass array as a parameter if `array[A_Index]` contains a function name instead of a function reference. However, if `array[A_Index]` is inherited from `array.base[A_Index]`, array will be passed as a parameter.

## Custom Objects

Objects in AutoHotkey are prototype-based rather than class-based. That is, an object can inherit properties and methods from its prototype or `base` object, but do not need to have a pre-defined structure. Properties and methods can also be added to (or removed from) an object or any of the objects it derives from at any time. However, AutoHotkey emulates classes by translating class definitions into ordinary objects. For more complex or specialized situations, the base object can override the standard behaviour by defining meta-functions.

To create an object derived from another object, scripts can assign a `base` or use the `new` keyword:

    baseObject := {foo: "bar"}
    obj1 := Object(), obj1.base := baseObject
    obj2 := {base: baseObject}
    obj3 := new baseObject
    MsgBox % obj1.foo " " obj2.foo " " obj3.foo

### Prototypes

Prototype or `base` objects are constructed and manipulated the same as any other object. For example, an ordinary object with one property and one method might be constructed like this:

    ; Create an object.
    thing := {}
    ; Store a value.
    thing.foo := "bar"
    ; Create a method by storing a function reference.
    thing.test := Func("thing_test")
    ; Call the method.
    thing.test()

    thing_test(this) {
       MsgBox % this.foo
    }

When `thing.test()` is called, thing is automatically inserted at the beginning of the parameter list. However, for backward-compatibility, this does not occur when a function is stored by name (rather than by reference) directly in the object (rather than being inherited from a base object). By convention, the function is named by combining the "type" of object and the method name.

An object is a prototype or base if another object derives from it:

    other := {}
    other.base := thing
    other.test()

In this case, other inherits foo and test from thing. This inheritance is dynamic, so if `thing.foo` is modified, the change will be reflected by `other.foo`. If the script assigns to `other.foo`, the value is stored in other and any further changes to `thing.foo` will have no effect on `other.foo`. When `other.test()` is called, its this parameter contains a reference to other instead of thing.

### Classes [v1.1.00+]

For convenience and familiarity, the "class" keyword can be used to construct a base object. A basic class definition might look like this:

    class ClassName extends BaseClassName
    {
        InstanceVar := Expression
        static ClassVar := Expression

        class NestedClass
        {
            ...
        }

        Method()
        {
            ...
        }
    }

When the script is loaded, this constructs an object and stores it in the global (or in v1.1.05+, super-global) variable ClassName. Prior to v1.1.05, to reference this class inside a function, a declaration such as `global ClassName` is required unless the function is assume-global. If `extends BaseClassName` is present, BaseClassName must be the full name of a previously defined class. The full name of each class is stored in `object.__Class`.

Class definitions can contain variable declarations, method definitions and nested class definitions.

        InstanceVar := Expression

Instance variable declarations [v1.1.01+] are evaluated each time a new instance of the class is created with the new keyword. The __New() method is called after all such declarations have been evaluated, including those defined in base classes. Expression can access other instance variables and methods via `this`, but all other variable references are assumed to be global. To access an instance variable, always specify the target object; for example, `this.InstanceVar`.

        static ClassVar := Expression

Class variable declarations [v1.1.00.01+] are evaluated only once, before the auto-execute section, in the order they appear in the script. Each declaration stores a value in the class object. As with any value or method contained by the class object, this value can be inherited by derived objects. Any variable references in Expression are assumed to be global. To access a class variable, always specify the class or derived object; for example, `ClassName.ClassVar`.

        class NestedClass
        {
            ...
        }

Nested class definitions allow a class object to be stored inside another class object rather than a separate global variable. In the example above, `class NestedClass` constructs an object and stores it in `ClassName.NestedClass`. Therefore, NestedClass may be inherited by any class or object which derives from ClassName.

        Method()
        {
            ...
        }

Method definitions look identical to function definitions. Each method has a hidden parameter named `this`, which typically contains a reference to an object derived from the class. However, it could contain a reference to the class itself or a derived class, depending on how the method was called. Methods are stored by reference in the class object.

In addition to the hidden parameter `this`, method definitions can use the pseudo-keyword `base` to invoke the base class of the class which contains the method definition. For example, `base.Method()` in the method above would be equivalent to `BaseClassName.Method.(this)`. Note that this differs from `this.base.base.Method()` in two other ways:

- It always invokes the base of the current class, even if `this` is derived from a sub-class of the current class.
- It passes `this` automatically, not `this.base.base`.

`base` only has special meaning if followed by a dot `.` or brackets `[]`, so code like `obj := base, obj.Method()` will not work. Scripts can disable the special behaviour of base by assigning it a non-empty value; however, this is not recommended. Since the variable base must be empty, performance may be reduced if the script omits #NoEnv.

### Construction and Destruction

Whenever a derived object is created with the `new` keyword [requires v1.1.00+], the `__New` method defined by its base object is called. This method can accept parameters, initialize the object and override the result of the `new` operator by returning a value. When an object is destroyed, `__Delete` is called. For example:

    m1 := new GMem(0, 20)
    m2 := {base: GMem}.__New(0, 30)

    class GMem
    {
        __New(aFlags, aSize)
        {
            this.ptr := DllCall("GlobalAlloc", "uint", aFlags, "ptr", aSize, "ptr")
            if !this.ptr
                return ""
            MsgBox % "New GMem of " aSize " bytes at address " this.ptr "."
            return this  ; This line can be omitted when using the 'new' operator.
        }

        __Delete()
        {
            MsgBox % "Delete GMem at address " this.ptr "."
            DllCall("GlobalFree", "ptr", this.ptr)
        }
    }

### Meta-Functions

    Method syntax:
    class ClassName {
        __Get([Key, Key2, ...])
        __Set([Key, Key2, ...], Value)
        __Call(Name [, Params...])
    }

    Function syntax:
    MyGet(this [, Key, Key2, ...])
    MySet(this [, Key, Key2, ...], Value)
    MyCall(this, Name [, Params...])

    ClassName := { __Get: Func("MyGet"), __Set: Func("MySet"), __Call: Func("MyCall") }

Meta-functions are methods defined by an object's base which can define exactly how the object should act when an unknown key is requested. For example, if `obj.key` has not been assigned a value, it invokes the __Get meta-function. Similarly, `obj.key := value` invokes __Set and `obj.key()` invokes __Call.

In these cases, the base object is invoked as follows:

- If this base object defines the appropriate meta-function, call it. If the meta-function explicitly `return`s, the return value is used as the result of the operation and no further processing occurs.

  Set: If the operation was successful, __Set should return the new value of the field, which may differ from the original r-value. This allows assignments to be chained, as in `a.x := b.y := z`. An empty string should be returned if the assignment failed, allowing the script to detect the error.

- If this is a get or call operation, search for a matching key in the base object's own fields.

  Get: If found, the value of that field is returned.
  Call: If found, the function stored in the field (by name or reference) is called, passing the original target object as the this parameter.

- Recursively invoke its own base object. This allows properties of an object to be "inherited" from its base, its base's base and so on.

If (and only if) no base object handles the operation, processing will continue as normal:

- Get: If the key is "base", the object's base is retrieved.
- Set: If the key is "base", the object's base is set; non-object values cause the existing base to be removed.

  Otherwise a new key-value pair is created and stored in the object.

- Call: A built-in method may be called.

Known limitations:

- Using `return` without a value is equivalent to `return ""`. This may be changed in a future version so that `return` can be used to "escape" from a meta-function without overriding the default behaviour.
- See Exit limitation.

#### Dynamic Properties

__Get and __Set can be used to implement properties whose values are calculated or restricted in some way. For example, they could be used to implement a "Color" object with R, G, B and RGB properties, where only the RGB value is actually stored:

    red  := new Color(0xff0000), red.R -= 5
    cyan := new Color(0x00ffff)

    MsgBox % "red: " red.R "," red.G "," red.B " = " red.RGB
    MsgBox % "cyan: " cyan.R "," cyan.G "," cyan.B " = " cyan.RGB

    class Color
    {
        __New(aRGB)
        {
            this.RGB := aRGB
        }

        __Get(aName)
        {
            if (aName = "R")
                return (this.RGB >> 16) & 255
            if (aName = "G")
                return (this.RGB >> 8) & 255
            if (aName = "B")
                return this.RGB & 255
        }

        __Set(aName, aValue)
        {
            if aName in R,G,B
            {
                aValue &= 255

                if      (aName = "R")
                    this.RGB := (aValue << 16) | (this.RGB & ~0xff0000)
                else if (aName = "G")
                    this.RGB := (aValue << 8)  | (this.RGB & ~0x00ff00)
                else  ; (aName = "B")
                    this.RGB :=  aValue        | (this.RGB & ~0x0000ff)

                ; 'Return' must be used to indicate a new key-value pair should not be created.
                ; This also defines what will be stored in the 'x' in 'x := clr[name] := val':
                return aValue
            }
        }
    }

#### Objects as Functions

When a call such as `obj.func(param)` is made, obj.func may contain a function name or an object. If obj.func contains an object, it is invoked using obj as the key. In most cases `obj.func[obj]` does not exist and obj.func's __Call meta-function is invoked instead. This may be used to change the behaviour of function calls in an abstract way, as shown in the example below:

    ; Create a prototype for an array of functions.
    FuncArrayType := {__Call: "FuncType_Call"}
    ; Create an array of functions.
    funcArray := {1: "One", 2: "Two", base: FuncArrayType}
    ; Create an object which uses the array as a method.
    obj := {func: funcArray}
    ; Call the method.
    obj.func("foo", "bar")

    FuncType_Call(func, obj, params*)
    {
        ; Call a list of functions.
        Loop % ObjMaxIndex(func)
            func[A_Index](params*)
    }

    One(param1, param2) {
        ListVars
        Pause
    }
    Two(param1, param2) {
        ListVars
        Pause
    }

Combining this technique with class definitions provides a convenient way to define dynamic properties similar to those in the previous section:

    blue := new Color(0x0000ff)
    MsgBox % blue.R "," blue.G "," blue.B

    class Properties
    {
        __Call(aTarget, aName, aParams*)
        {
            ; If this Properties object contains a definition for this half-property, call it.
            ; Take care not to use this.HasKey(aName), since that would recurse into __Call.
            if IsObject(aTarget) && ObjHasKey(this, aName)
                return this[aName].(aTarget, aParams*)
        }
    }

    class Color
    {
        __New(aRGB)
        {
            this.RGB := aRGB
        }

        class __Get extends Properties
        {
            R() {
                return (this.RGB >> 16) & 255
            }
            G() {
                return (this.RGB >> 8) & 255
            }
            B() {
                return this.RGB & 255
            }
        }

        ;...
    }

#### Sub-classing Arrays of Arrays

When a multi-parameter assignment such as `table[x, y] := content` implicitly causes a new object to be created, the new object ordinarily has no base and therefore no custom methods or special behaviour. `__Set` may be used to initialize these objects, as demonstrated below.

    x := {base: {addr: Func("x_Addr"), __Set: Func("x_Setter")}}

    ; Assign value, implicitly calling x_Setter to create sub-objects.
    x[1,2,3] := "..."

    ; Retrieve value and call example method.
    MsgBox % x[1,2,3] "`n" x.addr() "`n" x[1].addr() "`n" x[1,2].addr()

    x_Setter(x, p1, p2, p3) {
        x[p1] := new x.base
    }

    x_Addr(x) {
        return &x
    }

Since `x_Setter` has four mandatory parameters, it will only be called when there are two or more key parameters. When the assignment above occurs, the following takes place:

- `x[1]` does not exist, so `x_Setter(x,1,2,3)` is called (`"..."` is not passed as there are too few parameters).
  - `x[1]` is assigned a new object with the same base as `x`.
  - No value is returned – the assignment continues.
- `x[1][2]` does not exist, so `x_Setter(x[1],2,3,"...")` is called.
  - `x[1][2]` is assigned a new object with the same base as `x[1]`.
  - No value is returned – the assignment continues.
- `x[1][2][3]` does not exist, but since `x_Setter` requires four parameters and there are only three (`x[1][2], 3, "..."`), it is not called and the assignment completes as normal.

## Default Base Object

When a non-object value is used with object syntax, the default base object is invoked. This can be used for debugging or to globally define object-like behaviour for strings, numbers and/or variables. The default base may be accessed by using `.base` with any non-object value; for instance, `"".base`. Although the default base cannot be set as in `"".base := Object()`, the default base may itself have a base as in `"".base.base := Object()`.

#### Automatic Var Init

When an empty variable is used as the target of a set operation, it is passed directly to the __Set meta-function, giving it opportunity to insert a new object into the variable. For brevity, this example does not support multiple parameters; it could, by using a variadic function.

    "".base.__Set := Func("Default_Set_AutomaticVarInit")

    empty_var.foo := "bar"
    MsgBox % empty_var.foo

    Default_Set_AutomaticVarInit(ByRef var, key, value)
    {
        if (var = "")
            var := Object(key, value)
    }

#### Pseudo-Properties

Object "syntax sugar" can be applied to strings and numbers.

    "".base.__Get := Func("Default_Get_PseudoProperty")
    "".base.is    := Func("Default_is")

    MsgBox % A_AhkPath.length " == " StrLen(A_AhkPath)
    MsgBox % A_AhkPath.length.is("integer")

    Default_Get_PseudoProperty(nonobj, key)
    {
        if (key = "length")
            return StrLen(nonobj)
    }

    Default_is(nonobj, type)
    {
        if nonobj is %type%
            return true
        return false
    }

Note that built-in functions may also be used, but in this case the parentheses cannot be omitted:

    "".base.length := Func("StrLen")
    MsgBox % A_AhkPath.length() " == " StrLen(A_AhkPath)

#### Debugging

If allowing a value to be treated as an object is undesirable, a warning may be shown whenever a non-object value is invoked:

    "".base.__Get := "".base.__Set := "".base.__Call := Func("Default__Warn")

    empty_var.foo := "bar"
    x := (1 + 1).is("integer")

    Default__Warn(nonobj, p1="", p2="", p3="", p4="")
    {
        ListLines
        MsgBox A non-object value was improperly invoked.`n`nSpecifically: %nonobj%
    }

## Implementation

### Reference-Counting

AutoHotkey uses a basic reference-counting mechanism to automatically free the resources used by an object when it is no longer referenced by the script. Script authors should not invoke this mechanism explicitly, except when dealing directly with unmanaged pointers to objects. For more information, see ObjAddRef.

    ; Increment the object's reference count to "keep it alive":
    ObjAddRef(address)
    ...
    ; Decrement the object's reference count to allow it to be freed:
    ObjRelease(address)

However, ObjAddRef does not need to be used when initially obtaining an address via `Object(obj)`.

Generally each new copy of an object's address should be treated as an object reference, except that the script is responsible for calling ObjAddRef and/or ObjRelease as appropriate. For example, whenever an address is copied via something like `x := address`, ObjAddRef should be called to increment the reference count. Similarly, whenever the script is finished with a particular copy of the object's address, it should call ObjRelease. This ensures the object is freed when the last reference to it is lost - and not before then.

To run code when the last reference to an object is being released, implement the __Delete meta-function.

Known Limitations:

- Circular references must be broken before an object can be freed. For details and an example, see Freeing Objects.
- Although references in static and global variables are released automatically when the program exits, references in non-static local variables or on the expression evaluation stack are not. These references are only released if the function or expression is allowed to complete normally.

Although memory used by the object is reclaimed by the operating system when the program exits, __Delete will not be called unless all references to the object are freed. This can be important if it frees other resources which are not automatically reclaimed by the operating system, such as temporary files.

### Pointers to Objects

In some rare cases it may be necessary to pass an object to external code via DllCall or store it in a binary data structure for later retrieval. An object's address can be retrieved by `x := &obj`; however, if the variable obj is cleared, the object may be freed prematurely. To ensure this does not occur, use ObjAddRef as shown above or the `Object()` function as shown below:

    address := Object(object)

Additionally, this function can also be used to convert the address back into a reference:

    object := Object(address)

In either case the object's reference-count is automatically incremented so that the object is not freed prematurely.

Note that this function applies equally to objects not created by Object(), such as COM object wrappers or File objects.