You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Set与Dictionary未修改时内存地址不同,而Array却共享?

关于Swift中Set、Dictionary与Array的CoW(写时复制)地址疑惑解答

你搞混了两个完全不同的地址:变量本身在栈上的存储地址,和集合内部指向堆中实际数据的指针地址。

你的代码误区

你用address(of: &arr)打印的是栈上变量的地址——arr和newArr是两个独立的变量,正常情况下它们的栈地址必然不同(你看到Array的栈地址相同大概率是测试环境的特殊优化或者输出误差)。而CoW机制共享的是堆中的实际数据,不是栈上的变量本身。

正确查看CoW共享地址的方式

要验证Set、Dictionary的CoW是否生效,你需要查看它们内部指向堆数据的指针地址,而不是变量的栈地址。以下是修正后的代码:

import Foundation

// 打印变量内部存储的堆数据地址
func heapAddress<T>(of value: T) -> String {
    return withUnsafeBytes(of: value) { bytes in
        let ptr = bytes.baseAddress!.assumingMemoryBound(to: UnsafeRawPointer.self)
        return String(format: "%p", ptr.pointee)
    }
}

// Array测试
var arr: [Int] = [1,2,3]
var newArr = arr
print("Array堆地址 - arr: \(heapAddress(of: arr))")
print("Array堆地址 - newArr: \(heapAddress(of: newArr))") // 修改前地址相同

newArr.append(4)
print("修改后Array堆地址 - newArr: \(heapAddress(of: newArr))") // 修改后地址变化

// Set测试
var setValue: Set<Int> = [1,3,5]
var newSetValue = setValue
print("\nSet堆地址 - setValue: \(heapAddress(of: setValue))")
print("Set堆地址 - newSetValue: \(heapAddress(of: newSetValue))") // 修改前地址相同

newSetValue.insert(7)
print("修改后Set堆地址 - newSetValue: \(heapAddress(of: newSetValue))") // 修改后地址变化

// Dictionary测试
var dict: [String: Int] = ["zero":0, "one":1]
var newDict = dict
print("\nDictionary堆地址 - dict: \(heapAddress(of: dict))")
print("Dictionary堆地址 - newDict: \(heapAddress(of: newDict))") // 修改前地址相同

newDict["two"] = 2
print("修改后Dictionary堆地址 - newDict: \(heapAddress(of: newDict))") // 修改后地址变化

原理说明

Swift的Array、Set、Dictionary都是值类型,但它们的内部实现都用了CoW:

  • 变量本身存储在栈上,每个独立变量的栈地址必然不同;
  • 变量内部持有一个带引用计数的指针,指向堆中的实际数据;
  • 当你把一个集合赋值给另一个变量时,只是复制了这个指针,堆数据的引用计数+1,此时两个变量共享同一个堆数据(堆地址相同);
  • 当其中一个变量修改数据时,会检查引用计数:如果引用计数>1,就会复制一份堆数据,更新当前变量的指针指向新的堆数据,这就是写时复制的核心。

所以你之前看到Set、Dictionary的变量栈地址不同是完全正常的,这和CoW机制无关——CoW关注的是堆数据的共享,不是栈变量的地址。

内容的提问来源于stack exchange,提问作者홍진표

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 04:32:11