Returning Reference from Swift Function

I have a use case where I want to return reference from Swift Function just like we can do in C++.

This is How we do it in C++:

int & ReturnIntRef () noexcept
{
      static int a  = 4;

      return a;
}

Do we have equivalent of this in Swift ?

The answer is no.

Please take your C++ hat off. :slight_smile:

1 Like

Maybe to elaborate a bit on the "why" here:

Swift uses automatic reference counting to manage memory, whereas in C(++) you have to manually manage memory. Without going into too much details this means there is a fundamental difference in how you structure and design your code.

One such difference is that you cannot just mess around with the memory address of your objects, especially when it is not even a reference type (and structs are usually value types). Even if it is a reference type you cannot just "do the same as in C++", it's simply not the same context.

2 Likes

Thanks that helps.

Let's consider some semi-equivalent swift example:

var a = 0 // global, static or class variable

func fooPointer() -> UnsafeMutablePointer<Int> {
    withUnsafeMutablePointer(to: &a) { $0 } // BAD
}
var foo: Int {
    get { fooPointer().pointee }
    set { fooPointer().pointee = newValue }
}

print(foo) // 0
foo = 42
print(foo) // 42

This one is semantically close to C++ version although in Swift it is bad as it triggers UB (undefined behaviour) as withUnsafeMutablePointer specifically says: "The pointer argument is valid only for the duration of the function's execution." and it is bad to return it and use it like this. I don't remember if there are guarantees about memory address stability for mutable pointers created this way out of global / static variables or class variables, if to guess I'd say that most likely it will work (in practice) although there is no explicit guarantee about it.


var memory = calloc(8, 1)!

func barPointer() -> UnsafeMutablePointer<Int> {
    memory.assumingMemoryBound(to: Int.self)
}
var bar: Int {
    get { barPointer().pointee }
    set { barPointer().pointee = newValue }
}

print(bar) // 0
bar = 42
print(bar) // 42

This one is better IRT not triggering UB.

1 Like

There’s a more idiomatic way to express this:

var memory = {
    let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
    ptr.initialize(to: 0)
    return ptr
}()

func barPointer() -> UnsafeMutablePointer<Int> {
    return memory
}
5 Likes