If I have a struct in swift with inside a class attribute and I copy the struct object, is the class attribute copied or passed by reference?
Passed by reference. You can test it. Declare:
class A{}
struct B { let a = A()}
then:
let b = B()
print("A = \(unsafeAddressOf(b.a))")//0x0000600000019450
let b_copy = b
print("A = \(unsafeAddressOf(b_copy.a))")//0x0000600000019450
All properties of a struct are copied (as if you assigned (=
) each property of the old struct to the corresponding property of the new struct) when the struct is copied, regardless of type.
When you say "class attribute", I am assuming you mean a variable of reference type. (The type with the same name as a class denotes a reference type for references that point to objects of that class.) Copying a value of reference type (a reference) produces another reference that points to the same object. Note that "objects" are not values in Swift -- there are no "object types" -- rather, objects are always manipulated through references that point to them.
I tested the above experiment in swift 5: Let's see the result:
class A {
var id: Int
init(id: Int) {
self.id = id
}
}
struct B {
var grade: Int
var a: A
}
Experiment based on the result:
var a = A(id: 1)
var a_copy = a
var b1 = B(grade: 2, a: a)
var copy_b1 = b1
print(b1.a.id)
b1.a.id = 5
print(copy_b1.a.id)
print(b1.grade)
b1.grade = 3
print(copy_b1.grade)
Output:
1
5 // call by reference, same result
2
2 // call by value, no change in result
Conclusion:
struct does copy when we create another object of it. It copies its struct property (call by value) but refer the same instance of class property (call by reference)
Do experiment via address:
Do an Experiment on Class:
var a = A(id: 1)
var a_copy = a
withUnsafePointer(to: &a) { (address) in
print("address of a (class) = \(address)")
}
withUnsafePointer(to: &a_copy) { (address) in
print("address of a_copy (class) = \(address)")
}
withUnsafePointer(to: &a.id) { (address) in
print("address of a.id (struct) = \(address)")
}
withUnsafePointer(to: &a_copy.id) { (address) in
print("address of a_copy.id (struct) = \(address)")
}
Output
address of a (class) = 0x0000000114747f80
address of a_copy (class) = 0x0000000114747f88
address of a.id (struct) = 0x000060000285a390
address of a_copy.id (struct) = 0x000060000285a390
Observation 1:
Both instances of the class are referring to same location of its property.
Let's do the Experiment on struct:
print("\n\n\n")
withUnsafePointer(to: &b1) { (address) in
print("address of b1 (struct) = \(address)")
}
withUnsafePointer(to: &b1.grade) { (address) in
print("address of b1.grade (struct) = \(address)")
}
withUnsafePointer(to: &b1.a) { (address) in
print("address of b1.a (class) = \(address)")
}
withUnsafePointer(to: &b1.a.id) { (address) in
print("address of b1.a.id (class) = \(address)")
}
Output:
address of b1 (struct) = 0x0000000109382770
address of b1.grade (struct) = 0x0000000109382770
address of b1.a (class) = 0x0000000109382778
address of b1.a.id (class) = 0x0000600001e5cfd0
print("\n\n\n")
withUnsafePointer(to: ©_b1) { (address) in
print("address of copy_b1 (struct) = \(address)")
}
withUnsafePointer(to: ©_b1.grade) { (address) in
print("address of copy_b1.grade (struct) = \(address)")
}
withUnsafePointer(to: ©_b1.a) { (address) in
print("address of copy_b1.a (class) = \(address)")
}
withUnsafePointer(to: ©_b1.a.id) { (address) in
print("address of copy_b1.a.id (class) = \(address)")
}
Output:
address of copy_b1 (struct) = 0x0000000109382780
address of copy_b1.grade (struct) = 0x0000000109382780
address of copy_b1.a (class) = 0x0000000109382788
address of copy_b1.a.id (class) = 0x0000600001e5cfd0
conclusion: both &b1.a.id and ©_b1.a.id are referring the same address.
Seems, we have to consider modifying the object (as the optimizer will use the copy-on-write technique)
Value Type (User) contains Reference Type (Address)
observation:
- On assignment of value type, any value type (ex: User) that contains a reference type (ex: Address), that reference type (ex: Address) is always passed as a reference.
Reference Type (User) contains Value Types (Address)
observation:
- On assignment of reference type, any reference type (ex: User) contains value types (ex: Address), that value types (ex: Address) point to the same parent reference object (ex: User) (parent may contain many references - ex: both u1, u2 refers to same memory address).
© 2022 - 2024 — McMap. All rights reserved.