Understanding how ARC is different for Struct vs Class

Hi, I was trying to understand how swift manages it memory just wanted to verify my understanding on it. For Value Types i.e. Struct ARC (Automatic Reference Counting) is not there, Memory is Managed/Confined on the basis of scope of that Variable. And For Struct whenver we do assignment a Copy is been created.

For Classes, Swift Manages Memroy with the help of ARC i.e. whenever I create a instance of class its reference count get increased and when we assign same instance to new variable then it also result in increment of Reference Count. The Memory will get deallocated when all the variables pointing to that object are no longer in use.

Answered by DTS Engineer in 802067022

That’s basically correct.

There are a few extra things…

Values types include both structs and enums.

Reference types include classes, actors, and closures.

IMPORTANT There’s a subtle difference between value types and value semantics. I’ll come back to that below.

Keep in mind that values types can include reference type properties, and thus copying a value type may involve ARC traffic. For example, in this code:

class MyClass { }

struct MyStruct {
    var myClass: MyClass
}

let o = MyClass()
let s1 = MyStruct(myClass: o)
let s2 = s1

both s1 and s2 have reference to the same object (and o has a reference as well).

Note This is all conceptually. In reality, the optimiser can eliminate a lot of ARC traffic.

If you care about this stuff, I encourage you to watch WWDC 2024 Session 10217 Explore Swift performance. It’s a great talk.

Oh, and the speaker provided a ‘directory’s commentary’ for it here:

https://hachyderm.io/@rjmccall/112610472344271813

Rewatching the talk while reading that commentary is very much on my to-do list.


Finally, be aware that value types don’t necessarily have value semantics, and vice versa. For example, NSUUID is a reference type but it has value semantics (because it’s immutable). And it’s possible to create a value type with reference semantics:

struct NotAValueType {

    class Counter {
        static let shared: Counter = Counter()
        var count: Int = 0
    }

    private let myClass = Counter.shared

    func increment() {
        self.myClass.count += 1
    }

    var count: Int { self.myClass.count }
}

let s1 = NotAValueType()
let s2 = s1
print(s1.count)     // 0 (-:
print(s2.count)     // 0 (-:
s1.increment()
print(s1.count)     // 1 (-:
print(s2.count)     // 1 )-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

That’s basically correct.

There are a few extra things…

Values types include both structs and enums.

Reference types include classes, actors, and closures.

IMPORTANT There’s a subtle difference between value types and value semantics. I’ll come back to that below.

Keep in mind that values types can include reference type properties, and thus copying a value type may involve ARC traffic. For example, in this code:

class MyClass { }

struct MyStruct {
    var myClass: MyClass
}

let o = MyClass()
let s1 = MyStruct(myClass: o)
let s2 = s1

both s1 and s2 have reference to the same object (and o has a reference as well).

Note This is all conceptually. In reality, the optimiser can eliminate a lot of ARC traffic.

If you care about this stuff, I encourage you to watch WWDC 2024 Session 10217 Explore Swift performance. It’s a great talk.

Oh, and the speaker provided a ‘directory’s commentary’ for it here:

https://hachyderm.io/@rjmccall/112610472344271813

Rewatching the talk while reading that commentary is very much on my to-do list.


Finally, be aware that value types don’t necessarily have value semantics, and vice versa. For example, NSUUID is a reference type but it has value semantics (because it’s immutable). And it’s possible to create a value type with reference semantics:

struct NotAValueType {

    class Counter {
        static let shared: Counter = Counter()
        var count: Int = 0
    }

    private let myClass = Counter.shared

    func increment() {
        self.myClass.count += 1
    }

    var count: Int { self.myClass.count }
}

let s1 = NotAValueType()
let s2 = s1
print(s1.count)     // 0 (-:
print(s2.count)     // 0 (-:
s1.increment()
print(s1.count)     // 1 (-:
print(s2.count)     // 1 )-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Understanding how ARC is different for Struct vs Class
 
 
Q