I recently learned about CoW (copy-on-write). However, I have a question.
func address(of object: UnsafeRawPointer) -> String {
let address: Int = Int(bitPattern: object)
return String(format: "%p", address)
}
var arr: Array<Int> = [1, 2, 3]
var newArr: Array<Int> = arr
print("Addr of `arr`: (address(of: &arr))") // 0x600002e601e0
print("Addr of `newArr`: (address(of: &newArr))") // 0x600002e601e0
Both instances have the same memory address before changing the data in the array. However…
var setValue: Set<Int> = [1, 3, 5]
var newSetValue: Set<Int> = setValue
var dict: Dictionary<String, Int> = ["zero": 0, "one": 1]
var newDict: Dictionary<String, Int> = dict
print("Addr of `setValue`: (address(of: &setValue))") // 0x10000c098
print("Addr of `newSetValue`: (address(of: &newSetValue))") // 0x10000c0a0
print()
print("Addr of `dict`: (address(of: &dict))") // 0x10000c0a8
print("Addr of `newDict`: (address(of: &newDict))") // 0x10000c0b0
As far as I know, ‘CoW (copy-on-write)’ copies data when the value changes and shares the original resources before the value changes. In my opinion, ‘Array’ seems to share the same resources before the value changes. However, I wonder why ‘Set’ and ‘Dictionary’ have different memory address values when the value changes have not occurred.
(p.s. I understand that CoW is implemented internally in the ‘Collection Type’.)
홍진표 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You should see some warnings like this if you are using Swift 5.10:
Forming ‘UnsafeRawPointer’ to a variable of type ‘Set’; this is likely incorrect because ‘Set’ may contain an object reference.
This warning is added to point out this exact mistake that you are making.
Converting an Array
to UnsafeRawPointer
using the &
prefix gets you a pointer to the internal storage of the array, but converting Set
s and Dictionary
s do not have the same behaviour. You just get the stack address of that var
. dict
and newDict
are different variables, so of course their addresses are different.
I don’t think there is any public APIs for getting the address of the internal storage of a Set
or Dictionary
. For other types like Data
, there is Data.withUnsafeBytes
, though.
If you want to demonstrate copy-on-write behaviour with Set
and Dictionary
, I would use the “Allocations” tool in Instruments.app. It will count how many instances of the dictionary/set storage are allocated. My answer here demonstrates this for Set
.