Embarcadero Delphi Strings Reference counting


Example

Counting references on strings is thread-safe. Locks and exception handlers are used to safeguard the process. Consider the following code, with comments indicating where the compiler inserts code at compile time to manage reference counts:

procedure PassWithNoModifier(S: string);
// prologue: Increase reference count of S (if non-negative),
//           and enter a try-finally block
begin
  // Create a new string to hold the contents of S and 'X'. Assign the new string to S,
  // thereby reducing the reference count of the string S originally pointed to and
  // brining the reference count of the new string to 1.
  // The string that S originally referred to is not modified.
  S := S + 'X';
end;
// epilogue: Enter the `finally` section and decrease the reference count of S, which is
//           now the new string. That count will be zero, so the new string will be freed.
    
procedure PassWithConst(const S: string);
var
  TempStr: string;
// prologue: Clear TempStr and enter a try-finally block. No modification of the reference
//           count of string referred to by S.
begin
  // Compile-time error: S is const.
  S := S + 'X';
  // Create a new string to hold the contents of S and 'X'. TempStr gets a reference count
  // of 1, and reference count of S remains unchanged.
  TempStr := S + 'X';
end;
// epilogue: Enter the `finally` section and decrease the reference count of TempStr,
//           freeing TempStr because its reference count will be zero.

As shown above, introducing temporary local string to hold the modifications to a parameter involves the same overhead as making modifications directly to that parameter. Declaring a string const only avoids reference counting when the string parameter is truly read-only. However, to avoid leaking implementation details outside a function, it is advisable to always use one of const, var, or out on string parameter.