Pascal & Object Pascal DISCUSSION

Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

Started by winnermohamed Pascal parameter passingvar parameterconst parameterdynamic array referenceopen array parameters
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

winnermohamed Pascal & Object Pascal Forum
#1

My unit has a record type with an array[0..255] of Integer inside, a few TStringList objects and several dynamic arrays, and I pass them to procedures without thinking much about the parameter kind. Two things surprised me: a procedure that takes a dynamic array by value changed the caller's elements, and a procedure that takes a TStringList by value added lines to the caller's list.

What is actually copied for each kind of type, and when should I write var, const or out?

Community replies 5

Re: Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

#2

A value parameter copies the variable, and the question is what the variable is. For integers, floats, records and static arrays the variable is the data, so your record is copied in full: 256 × 4 = 1024 bytes on every call. For class instances and dynamic arrays the variable is only a reference, so the copy is a second pointer to the same data.

That is why List.Add and Arr[0] := 5 inside the procedure are visible to the caller, while assigning a new object to List or calling SetLength on Arr inside only affects the local copy of the reference.

Re: Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

#3

var passes the address of the caller's variable, so the procedure can replace the whole thing: change a record's fields, resize the caller's dynamic array, or make the caller's object variable point to a new instance. The actual argument must be a variable of exactly the declared type.

out is like var but states that the incoming value is not used. For managed types such as strings, dynamic arrays and interfaces the compiler clears the variable before the call, so do not read an out parameter before assigning it.

Re: Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

#4

const is the right default for anything you only read and that is larger than a register. The compiler forbids assignment to it and is then free to pass large records and static arrays by reference instead of copying, so the 1024-byte copy disappears. For strings and dynamic arrays it also skips the reference-count increment and decrement and the hidden try ... finally that protects them, which is noticeable in small routines called in tight loops.

Open array parameters such as A: array of Integer deserve a special mention: by value, the whole array is copied onto the stack at the call, which for a large array can exhaust it. Declare them const unless you need a private copy.

Re: Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

#5

One caveat with const on strings and other reference-counted types: because no reference is taken, the parameter is only valid while the caller's variable is unchanged. If the procedure, directly or through something it calls, assigns to the very global or field that was passed in, the old string can be freed while the const parameter still points at it. The symptom is garbage text or an access violation far from the cause. It is rare, but if a routine modifies shared state that might also be its argument, take the parameter by value.

const also does not make an object immutable: with const List: TStringList you cannot reassign List, but you can still call List.Add.

Re: Delphi and Free Pascal parameters: when to use value, var, const or out, and what gets copied?

#6

A workable rule set: ordinal and floating-point values by value; strings, records, static and open arrays as const when read-only; var when the caller must see a replaced value or a resized array; out for pure results; objects by value or const, since the reference is all that is passed anyway. If a dynamic array must not be altered by the callee, const is not enough, because the elements stay writable through the reference; pass Copy(Arr) to hand over a separate array.

When passing by reference must be guaranteed, for example for a record whose address is kept, Free Pascal has constref and newer Delphi versions have the [ref] attribute for const parameters.

TEP COMMUNITY