Reputation: 3448
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?
Upvotes: 20
Views: 10399
Reputation: 423
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).
Upvotes: 4
Reputation: 2364
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
}
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
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
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
Upvotes: 5
Reputation: 122499
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.
Upvotes: 10
Reputation: 21808
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
Upvotes: 39