The story of one mother & two sons: value type vs reference type in Swift

Boudhayan Biswas
May 21 Β· 6 min read

Swift is a mother🀰and it has two sons πŸ‘¬-

  • Value Type πŸš΄πŸ»β€β™€οΈ
  • Reference Type πŸš΄β€β™‚οΈ

But what are their characteristics?πŸ€Όβ€β™‚οΈ

Do they behave the same or opposite to each other? πŸ§˜β€β™‚οΈ

Swift is a multi-paradigm programming language developed by Apple for iOS, macOS, watchOS, tvOS, Linux, and z/OS.πŸ’ͺ

Just like other object-oriented programming languages, Swift has classes as building blocks which can define methods, properties, initializers, and can conform to protocols, support inheritance & polymorphism.πŸ‘

But, wait wait waitβ€¦πŸ–πŸ–πŸ–

Swift has structs also and it can define methods, properties, initializers and can conform to protocols with only one exception of inheritance.😳

What? Now I am confused!!! πŸ€”πŸ€”πŸ€”

Now let’s spice up your confusion: structs are not only the value types in Swift. Tuples and enums are also value types. Classes are also not the only one used as a reference type. Functions and closures are also reference types. But as a token of relief, we at least know the primary focus & specialization of usage of these types.😟

So up to this point, we are left with only one big confusion with the usage of structs and classes.🀬

So, let’s go and clear the confusions going around.πŸ’β€β™‚οΈ

Storage Locations

There are three types of storage available:

  • Register πŸš€
  • Stack β˜„οΈ
  • Heap 🎯

The objects that have a shorter lifespan are stored inside registers or the stack and those that have a longer lifespan are stored inside the heap.πŸ‘

A value type stores its contents in memory allocated in the stack, so we can say value types are allocated in the stack in Swift. 🀫

But there is a common misconception about value types, have you heard it?πŸ’β€β™‚οΈ

The misconception is that most people think value types are always stored in the Stack.

❌❌ Wait a minute β€” this is not the case always. ❌❌

Value types can be stored inside the stack when they are either temporary or local variables. But what if a value type is contained inside a reference type?

In this situation, it can be stored inside the heap memory. πŸ˜†

Wow…that’s cool!!!πŸ†’

So the value types can be stored inside the register, stack or heap depending on their lifespan, whether they are short lived or long lived. If it is a local variable it can live inside the stack and if it is a part of class then it can live inside heap memory also.βœ…

On the other hand, reference type stores its contents in memory allocated in the heap memory and the variable holds only a reference to that memory location where actual data has been stored. πŸ’ πŸ’ 

How does it work for reference type?🧐

So for reference type, it is quite a common situation when there can be several variables holding the reference to the same memory location.βš”οΈ

When a value type instance is assigned to a variable or passed to a function, the instance is copied and assigned to that variable. But with the reference type, only the reference gets copied and the new variable holds the same reference to the same memory location. 🌞

Differences in terms of Mutability

There can be two states for a variable:

  • πŸ’‚β€β™€ ️Mutable πŸ’‚β€β™€
  • πŸ•΅οΈβ€β™‚οΈ Immutable πŸ•΅οΈβ€β™‚οΈ

If a value type instance is assigned to an immutable variable, then the instance also becomes immutable. As a result, we can not make any changes to that instance.πŸ€¦β€β™‚οΈ

If a value type instance is assigned to a mutable variable, then only it makes the instance mutable. πŸ™‹β€β™‚οΈ

But things are totally different for reference types. The variable and the instance it is assigned to are totally different. If we declare an immutable variable holding a reference to a class, this means that the reference it is holding will never change. We can not the change the reference and it will always point to the same reference. 🎯

Structural Types

Values of structural types are compared for equality in terms of their attributes or elements. We can say a value type is equal to another if and only if all of the corresponding attributes are equal. 🀬🀬🀬

Umm…too many strong words…what do you mean??πŸ€”

Let’s say, we have a Person value type which has attributes like firstName and lastName.

struct Person {   var firstName: String   var lastName: String}var person1 = Person(firstName: "foo", lastName: "bar")var person2 = Person(firstName: "foo", lastName: "bar")

Here both person1 & person2 instances are holding the same value for firstName (β€œfoo”) and lastName (β€œbar”). So as per our understanding, we can say that the two instances are equal to each other since their attributes (firstName & lastName) are holding the same values.

But it’s not only limited to this: in the future, any two person instances holding the same values for firstName & lastName will be equal to each other.

So as per our understanding till this point, we can say that:

Value Types do not have identity, so there can be no reference to them. Value types are faceless.🀯

What? How can you say that?😷😷😷

var myAge: Int = 21
var friendAge: Int = 21

Both myAge & friendAge are integer type variable with value 21.

Can we distinguish one from the other? πŸ₯Ί

No, because they are holding the same value.🍺

An integer variable with value 21 cannot be different from another integer variable which is also having the value 21. As simple as that.πŸ‘πŸ‘πŸ‘

Not having an identity gives value types another advantage: if you think practically, then you can imagine if you do not have an identity then anyone with same characteristics can replace or substitute you. 😱😱😱

The same we can think for us as humans also. If I don’t have an identity then anyone with same characteristics can replace me😑😑😑. It’s good for us that we have an identity otherwise it would be a great risk to our existence.😳

But for value types, they don’t have an identity and it is an advantage to them. 🀘

What are the benefits of using Value Types?

πŸ’ͺ No Race Conditions and Deadlocks: πŸ’ͺ

For values types in a multi-threaded environment, it is impossible for one thread to mutate the state of the instance while it is being used by another thread. So we can say that there will be no race conditions or deadlocks.

βš”οΈ No Retain Cycles: βš”οΈ

When there are two reference type instances that are holding strong references to each other and preventing each other from being deallocated from memory, it is called a retain cycle. Since value types don’t work as a reference, so we can say there will be no retain cycles for value types.

πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘§ Automatic Reference Counting: πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘§

For reference type, Swift uses automatic reference counting to keep track of all the live or active objects and deallocates the instance only when there are no more strong references to it. If we think a little bit, then we can say that it is kind of a heavy operation because Swift runtime needs to keep track of the objects always. But since value types are allocated in the stack, it does not need ARC. So it is cheaper and fasterπŸ†πŸ†.

But wait...How does it manage memory for Array, Dictionary and String?πŸ€”

Since we can not know what will be the actual size of an array, a dictionary, and a string at compile time, there is no scope for them to be allocated at compile time. Though they are value types internally, they can not be allocated in stack. They need to be allocated in heap memory, and to manage this, Swift comes up with copy on write.😎

But what is this?😩

When we say one instance is a copy of another instance, this really means they are the same, that they contain the same values. But in Swift, for these above types (Array, Dictionary, String, etc), an actual copy has been made on heap only when an instance is mutated. This is called a performance optimization technique for value types.🀩🀩🀩

Conclusion

There is no hard rule which defines when to use value type and when to use reference type. Value types have some unique advantages over reference types and vice versa. They both are unique in their own way. It really depends on your requirements and what you are trying to achieve. You should know the semantics of your code because you only know your code best, so it’s up to you to choose. You have the full freedom.

So rather than fighting over value type vs reference type, use them intelligently.

πŸ™πŸ™πŸ™ Cheers!!! Thank you for reading!! πŸ™πŸ™πŸ™

βœ…βœ…βœ…You can find me on Twitter.βœ…βœ…βœ…

freeCodeCamp.org

This is no longer updated. Go to https://freecodecamp.org/news instead

Boudhayan Biswas

Written by

Swift Developer. In love with Python & Machine Learning.

freeCodeCamp.org

This is no longer updated. Go to https://freecodecamp.org/news instead

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium β€” and support writers while you’re at it. Just $5/month. Upgrade