Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An in-out parameter allows a function to modify the value of an argument passed into it, with those modifications persisting in the original variable after the function execution completes. By default, Swift function parameters are constants (let); the inout keyword overrides this behavior, enabling mutable parameter passing.

Syntax

To declare an in-out parameter, place the inout keyword directly before the parameter’s type. When invoking the function, prepend the argument with an ampersand (&) to explicitly acknowledge that the variable’s value can be mutated by the function.
func mutateInteger(_ value: inout Int) {
    value *= 2
}

var counter = 10
mutateInteger(&counter) 
// counter is now 20

The Memory Model: Copy-In Copy-Out

Swift does not strictly use pass-by-reference for in-out parameters. Instead, it employs a model known as copy-in copy-out (or call by value result). The logical lifecycle is as follows:
  1. When the function is called, the value of the argument is copied.
  2. Within the function body, the copy is modified.
  3. When the function returns, the modified copy is assigned back to the original argument.
Note: As a compiler optimization, if the argument is stored at a physical address in memory, Swift may pass a pointer to the original memory location (pass-by-reference) to avoid allocation overhead. However, the semantic behavior remains strictly copy-in copy-out.

Rules and Constraints

  • Variables Only: You can only pass a variable (var) as an in-out argument. Constants (let) and literals cannot be passed because they are immutable.
  • No Default Values: In-out parameters cannot have default values.
  • No Variadics: Variadic parameters (...) cannot be marked as inout.
  • Property Observers: If you pass a property that has observers (willSet and didSet) as an in-out argument, the getter is called when the function begins, and the setter is called when the function returns. The observers will trigger regardless of whether the function actually mutated the value.
  • Closure Capture: An inout parameter cannot be captured by an escaping closure. It can only be captured by a non-escaping closure, ensuring the parameter does not outlive the function scope.

Exclusive Access to Memory

Swift enforces memory safety by requiring exclusive access to a variable being modified. Passing a variable as an in-out parameter initiates a write access to that variable for the entire duration of the function call. Attempting to access the original variable from outside the function while the function is executing (e.g., via a global reference or a closure) will result in a compile-time error or a runtime crash due to conflicting memory access.
var globalStepSize = 1

func increment(_ number: inout Int) {
    // ERROR: Conflicting accesses to 'globalStepSize'
    number += globalStepSize 
}

increment(&globalStepSize)
Master Swift with Deep Grasping Methodology!Learn More