Is Swift Pass By Value or Pass By Reference

SwiftPass by-ReferencePass by-ValuePass by-Pointer

Swift Problem Overview


I'm really new to Swift and I just read that classes are passed by reference and arrays/strings etc. are copied.

Is the pass by reference the same way as in Objective-C or Java wherein you actually pass "a" reference or is it proper pass by reference?

Swift Solutions


Solution 1 - Swift

Types of Things in Swift

The rule is:

  • Class instances are reference types (i.e. your reference to a class instance is effectively a pointer)

  • Functions are reference types

  • Everything else is a value type; "everything else" simply means instances of structs and instances of enums, because that's all there is in Swift. Arrays and strings are struct instances, for example. You can pass a reference to one of those things (as a function argument) by using inout and taking the address, as newacct has pointed out. But the type is itself a value type.

What Reference Types Mean For You

A reference type object is special in practice because:

  • Mere assignment or passing to function can yield multiple references to the same object

  • The object itself is mutable even if the reference to it is a constant (let, either explicit or implied).

  • A mutation to the object affects that object as seen by all references to it.

Those can be dangers, so keep an eye out. On the other hand, passing a reference type is clearly efficient because only a pointer is copied and passed, which is trivial.

What Value Types Mean For You

Clearly, passing a value type is "safer", and let means what it says: you can't mutate a struct instance or enum instance through a let reference. On the other hand, that safety is achieved by making a separate copy of the value, isn't it? Doesn't that make passing a value type potentially expensive?

Well, yes and no. It isn't as bad as you might think. As Nate Cook has said, passing a value type does not necessarily imply copying, because let (explicit or implied) guarantees immutability so there's no need to copy anything. And even passing into a var reference doesn't mean that things will be copied, only that they can be if necessary (because there's a mutation). The docs specifically advise you not to get your knickers in a twist.

Solution 2 - Swift

Everything in Swift is passed by "copy" by default, so when you pass a value-type you get a copy of the value, and when you pass a reference type you get a copy of the reference, with all that that implies. (That is, the copy of the reference still points to the same instance as the original reference.)

I use scare quotes around the "copy" above because Swift does a lot of optimization; wherever possible, it doesn't copy until there's a mutation or the possibility of mutation. Since parameters are immutable by default, this means that most of the time no copy actually happens.

Solution 3 - Swift

It is always pass-by-value when the parameter is not inout.

It is always pass-by-reference if the parameter is inout. However, this is somewhat complicated by the fact you need to explicitly use the & operator on the argument when passing to an inout parameter, so it may not fit the traditional definition of pass-by-reference, where you pass the variable directly.

Solution 4 - Swift

Here is a small code sample for passing by reference. Avoid doing this, unless you have a strong reason to.

func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
    value1 = "my great computation 1";
    value2 = 123456;
}

Call it like this

var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);

Solution 5 - Swift

The Apple Swift Developer blog has a post called Value and Reference Types that provides a clear and detailed discussion on this very topic.

To quote:

> Types in Swift fall into one of two categories: first, “value types”, > where each instance keeps a unique copy of its data, usually defined > as a struct, enum, or tuple. The second, “reference types”, where > instances share a single copy of the data, and the type is usually > defined as a class.

The Swift blog post continues to explain the differences with examples and suggests when you would use one over the other.

Solution 6 - Swift

When you use inout with an infix operator such as += then the &address symbol can be ignored. I guess the compiler assumes pass by reference?

extension Dictionary {
    static func += (left: inout Dictionary, right: Dictionary) {
        for (key, value) in right {
            left[key] = value
        }
    }
}

origDictionary += newDictionaryToAdd

And nicely this dictionary 'add' only does one write to the original reference too, so great for locking!

Solution 7 - Swift

Classes and structures

One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.

Closures

If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles

ARC(Automatic Reference Counting)

Reference counting applies only to instances of classes. Structures and enumerations are value types, not reference types, and are not stored and passed by reference.

Solution 8 - Swift

Classes are passed by references and others are passed by value in default. You can pass by reference by using the inout keyword.

Solution 9 - Swift

Swift assign, pass and return a value by reference for reference type and by copy for Value Type

[Value vs Reference type]

If compare with Java you can find matches:

  • Java Reference type(all objects)

  • Java primitive type(int, bool...) - Swift extends it using struct

Solution 10 - Swift

struct is a value type so it's always passed as a value. let create struct

    //STEP 1 CREATE PROPERTIES
struct Person{
    var raw : String
    var name: String
    var age: Int
    var profession: String
    // STEP 2 CREATE FUNCTION
    func personInformation(){
        print("\(raw)")
        print("name : \(name)")
        print("age : \(age)")
        print("profession : \(profession)")
    }
}
//allow equal values
B = A then call the function
A.personInformation()
B.personInformation()
print(B.name)

it have the same result when we change the value of 'B' Only Changes Occured in B Because A Value of A is Copied, like B.name = "Zainab" a change occurs in B's name. it is Pass By Value

Pass By Reference Classes Always Use Pass by reference in which only address of occupied memory is copied, when we change similarly as in struct change the value of B , Both A & B is changed because of reference is copied,.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiongran_profaciView Question on Stackoverflow
Solution 1 - SwiftmattView Answer on Stackoverflow
Solution 2 - SwiftNate CookView Answer on Stackoverflow
Solution 3 - SwiftnewacctView Answer on Stackoverflow
Solution 4 - SwiftChris AmelinckxView Answer on Stackoverflow
Solution 5 - SwiftwhyceewhiteView Answer on Stackoverflow
Solution 6 - SwiftJules BurtView Answer on Stackoverflow
Solution 7 - SwiftmohsenView Answer on Stackoverflow
Solution 8 - SwiftBahram ZangeneView Answer on Stackoverflow
Solution 9 - SwiftyoAlex5View Answer on Stackoverflow
Solution 10 - SwiftNadia TariqView Answer on Stackoverflow