Is Swift Pass by Value or Pass by Reference

Is Swift Pass By Value or Pass By Reference

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.

Are Swift functions assigned/passed by value or by reference?

From the Apple documentation:

In the example above, incrementBySeven and incrementByTen are constants, but the closures these constants refer to are still able to increment the runningTotal variables that they have captured. This is because functions and closures are reference types.

Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be a reference to the function or closure.

Is conditional binding in swift pass by value or reference?

It just depends upon whether the type wrapped by the optional was a value type or reference type. If reference type, it's obviously pass by reference. If value type, it's copied (unless CoW, copy-on-write, in which case it's copied if and when it's mutated).

In this case, CMSensorDataList is a class, so it's a reference to that instance, not a copy of it.

Pass constant parameter by reference

Can I pass a constant by reference?

Not that I'm aware of. However, you should never need to do so yourself.

In the specific case you raise with a Dictionary, you're dealing with a collection that stores its contents indirectly. At its simplest level, you can think of it as a structure that just has a single property, which is merely a reference to the actual storage for the keys & values of the dictionary.

Passing that struct, the dictionary, by value is equivalent to just passing a reference about. Multiple dictionaries can view the same key & value storage through that reference. However, a unique copy of the storage will be taken on mutation if necessary – this is called copy-on-write, and allows for value semantics without the overhead of copying the entire buffer every time the dictionary structure is copied.

So for that reason, there is absolutely no need for a pass-by-reference here. Just pass the dictionary normally (i.e by value – that is, not with & such as with inout and pointer parameters).

In the more general case of having a large structure that you want to avoid copying when passing by value to a function – the compiler already has you covered. It can perform various clever optimisations to reduce copying; one of which is passing the structure by reference to a function. I go into more detail about this in this Q&A.

It's really not something you should need to think about unless:

  • You actually need caller-side mutation (in which case, you want a var anyway).

  • You've specifically identified a performance bottleneck (in that case, you may well benefit from making your own copy-on-write structure).

Inout vs pass by reference swift optimization

As many know, inout in swift does NOT pass by reference, rather it makes an initial copy to the function then copies the values back on the return. This sounds expensive.

It's not. It's copying an instance of a [Int: Bool] (a.k.a. Dictionary<Int, Bool>) which is only a single pointer. See for yourself, with print(MemoryLayout<[Int: Bool]>.size).

Passing a value type as reference in Swift

structs are always passed by value. The whole point of using a struct is to have it behave as a value type. If you need delegation (which usually implies mutable state), you should be using a class.

If you really really need to, you could force pass-by-reference by using an inout parameter, but that is not recommended in general. You could also use a box type to simulate passing by reference. But, in general, you should just use a class if you need reference behavior.

Passing variables by reference in Swift

Copying arrays and strings is cheap (almost free) as long as you don't modify it. Swift implements copy-on-write for these collections in the stdlib. This isn't a language-level feature; it's actually implemented explicitly for arrays and strings (and some other types). So you can have many copies of a large array that all share the same backing storage.

inout is not the same thing as "by reference." It is literally "in-out." The value is copied in at the start of the function, and then copied back to the original location at the end.

Swift's approach tends to be performant for common uses, but Swift doesn't make strong performance promises like C++ does. (That said, this allows Swift to be faster in some cases than C++ could be, because Swift isn't as restricted in its choice of data structures.) As a general rule, I find it very difficult to reason about the likely performance of arbitrary Swift code. It's easy to reason about the worst-case performance (just assume copies always happen), but it's hard to know for certain when a copy will be avoided.

Does Swift have something like ref keyword that forces parameter to be passed by reference?

Use the inout qualifier for a function parameter.

func swapTwoInts(a: inout Int, b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}

swapTwoInts(&someInt, &anotherInt)

See Function Parameters and Return Values in the docs.

Swift how to pass by value of a object

If your class is subclass of NSObject,better to use NSCopying

class Fraction:NSObject,NSCopying{
var a:Int
var b:NSString?
required init(a:Int){
self.a = a
}
func toString() -> String{
return "\(self.a)"
}
func copyWithZone(zone: NSZone) -> AnyObject {
let theCopy=self.dynamicType.init(a: self.a)
theCopy.b = self.b?.copy() as? NSString
return theCopy
}
}
class XXXclass{
class func A_plusplus(f:Fraction){
f.a++
f.b = "after"
}

}

var object = Fraction(a:10)
object.b = "before"
print("before run func = " + object.toString())
print(object.b!) //“Before”

XXXclass.A_plusplus(object.copy() as! Fraction)
print("after ran func =" + object.toString() )
print(object.b!)//“Before”

If it is just a common swift class,You have to create a copy method

class Fraction{
var a: Int
init(a:Int){
self.a = a
}
func toString() -> String{
return "\(self.a)"
}
func copy()->Fraction{
return Fraction(a: self.a)
}
}
class XXXclass{
class func A_plusplus(f:Fraction){
f.a++
}
}
var object = Fraction(a:10)
print("before run func = " + object.toString())
XXXclass.A_plusplus(object.copy())
print("after ran func =" + object.toString() )

To make it clear,you have to know that there are mainly two types in swift

  1. Reference types. Like Class instance,function type
  2. Value types,Like struct and others(Not class instance or function type)

If you pass in a Reference types,you pass in the copy of Reference,it still point to the original object.

If you pass in a Copy type,you pass in the copy of value,so it has nothing to do with the original value

Let us talk about inout,if you use it,it pass in the same object or value.It has effect on Value type

func add(inout input:Int){
input++
}

var a = 10
print(a)//10
add(&a)
print(a)//11

Issue with pass by value vs pass by reference in Swift?

Your problem is that Card is a struct, so this line:

for var card in cards {

creates a copy of each card in cards, so setting any properties on that copy will not modify the card in your cards array.

To fix this, loop over the indices of the array and refer to the cards as cards[idx]:

struct SetGame {

private(set) var cards = [Card]()
mutating public func chooseCard(at index: Int) {

//TODO: Assertion here for index being < cards.count
print("chooseCard(at index: \(index)")
cards[index].isChosen = !cards[index].isChosen // toggle isChosen when card is selected

if !cards[index].isMatched && cards[index].isChosen {
//print("Card not matched, so we're good to go...")
for idx in cards.indices {
if cards[idx].isChosen {
matchingCards.append(cards[idx])
// see if we have enough cards to match
if matchingCards.count > 2 {
//TODO: Need to call match logic here and set each matched card to .isMatched = true if matched
if cards[idx].isMatched {
print("Yay, matched!")
} else {
print("Card is not matched, flipping back over")
/*** THIS LINE NOT REFLECTING IN THE UI! ***/
cards[idx].isChosen = !cards[idx].isChosen // flip the unmatched card back over
}
}
}
}
matchingCards.removeAll() // clear out all the cards from the matching
} else {
print("Card is either matched or being deselected...")
}
}

or consider making Card a class so that when you are referring to a Card you know you are referring to the same object.



Related Topics



Leave a reply



Submit