最近在做内存优化的时候,发现了一些东西,记录一下;
我们经常会使用数组去存储数据,然后再控制器中使用,但是当我们共享数据的时候,我们经常会直接使用 =
操作来进行 赋值
,这样的过程是一个深拷贝的过程,先有如下代码:
class Tree: NSObject {
var name: String = "T"
init(name: String) {
self.name = name
}
override var description: String {
return name
}
}
class AAA {
var arr: [Tree] = []
}
struct MMM {
var t: Tree
var description: String {
return t.name
}
}
func test() {
let t1 = Tree.init(name: "1")
let t2 = Tree.init(name: "2")
let t3 = Tree.init(name: "3")
let a = AAA.init()
let b = a
a.arr = [t1, t2, t3]
print(a.arr,"---", b.arr)
let t4 = Tree.init(name: "4")
a.arr.append(t4)
print(a.arr,"+++", b.arr)
let t5 = Tree.init(name: name)
let t6 = t5
print("t5", address(of: t5))
print("t6", address(of: t6))
print("t5.name", address(of: t5.name),"t6.name", address(of: t6.name))
t5.name = "newName"
print("t5.newName", t5.name, address(of: t5.name),"t6.name", t6.name, address(of: t6.name))
var m1 = MMM.init(t: t1)
var m2 = MMM.init(t: t2)
var m3 = MMM.init(t: t3)
var mArr = [m1, m2, m3]
var nArr = mArr
var m4 = MMM.init(t: t4)
nArr.append(m4)
mArr.append(m1)
print("pppppp", mArr, nArr)
print("mArr", address(of: &mArr))
print("nArr", address(of: &nArr))
print("mArr[0]", address(of: &mArr[0]))
print("mArr[1]", address(of: &mArr[1]))
print("mArr[2]", address(of: &mArr[2]))
print("mArr[3]", address(of: &mArr[3]))
print("nArr[0]", address(of: &nArr[0]))
print("nArr[1]", address(of: &nArr[1]))
print("nArr[2]", address(of: &nArr[2]))
print("nArr[3]", address(of: &nArr[3]))
print("m1", address(of: &m1))
print("m2", address(of: &m2))
print("m3", address(of: &m3))
print("m4", address(of: &m4))
print("mArr[0].t", address(of: &mArr[0].t))
print("mArr[1].t", address(of: &mArr[1].t))
print("mArr[2].t", address(of: &mArr[2].t))
print("mArr[3].t", address(of: &mArr[3].t))
print("nArr[0].t", address(of: &nArr[0].t))
print("nArr[1].t", address(of: &nArr[1].t))
print("nArr[2].t", address(of: &nArr[2].t))
print("nArr[3].t", address(of: &nArr[3].t))
}
func address<T: AnyObject>(of object: T) -> String {
let addr = unsafeBitCast(object, to: Int.self)
return String(format: "%p", addr)
}
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
记录结果如下:
[1, 2, 3] --- [1, 2, 3]
[1, 2, 3, 4] +++ [1, 2, 3, 4]
t5 0x1d022e400
t6 0x1d022e400
t5.name 0x1d04598e0 t6.name 0x1d04598e0
t5.newName newName 0x1d04598e0 t6.name newName 0x1d04598e0
pppppp [AAA.MMM(t: 1), AAA.MMM(t: 2), AAA.MMM(t: 3), AAA.MMM(t: 1)] [AAA.MMM(t: 1), AAA.MMM(t: 2), AAA.MMM(t: 3), AAA.MMM(t: 4)]
mArr 0x1d00948e0
nArr 0x1d0094890
mArr[0] 0x16faed4f8
mArr[1] 0x16faed4f0
mArr[2] 0x16faed4e8
mArr[3] 0x16faed4e0
nArr[0] 0x16faed4d8
nArr[1] 0x16faed4d0
nArr[2] 0x16faed4c8
nArr[3] 0x16faed4c0
m1 0x16faed558
m2 0x16faed550
m3 0x16faed548
m4 0x16faed530
mArr[0].t 0x16faed4b8
mArr[1].t 0x16faed4b0
mArr[2].t 0x16faed4a8
mArr[3].t 0x16faed4a0
nArr[0].t 0x16faed498
nArr[1].t 0x16faed490
nArr[2].t 0x16faed488
nArr[3].t 0x16faed480
总结:
1. 数组赋值是深拷贝的过程,因为是值类型;类是浅拷贝,因为类是引用类型;
2. 当我们在类里面有值类型的变量的时候,进行拷贝,拷贝的两个对象(t5 和 t6)的地址以及值类型变量(t5.name 和 t6.name)的地址都是一样的,如果改变一个对象的值类型变量,两个对象(t5.name 和 t6.name)的都会被改变;
3. 值类型有值类型的变量的时候,复制是深复制,mArr 还有 nArr 以及其数组内的内容都不一样
此次获取地址来自喵神的 gist
自己之前找的打印地址的方法都不对,在 swift4 中使用此法可以正确打印地址
网友评论