值类型与引用类型的区别
暂且把值类型看做 struct(结构),引用类型看做 class(类)
- struct在栈上直接储存元素,class在栈上储存指针,指向堆上的对象
- 赋值时,struct在复制元素,class复制指针。
- 这两者都需要初始化,或者直接赋值,或者使用初始化器,赋值的本质是编译器后台添加初始化器初始化为你的赋值。
- 只有引用类型需要析构器,析构器伴随引用计数归零调用。引用计数增减规则可以简单概括为指向该对象的指针增减,当指向它的指针数为零时,就意味着该对象不再被任何资源占用,于是析构器自动调用,对象销毁。
- 在值类型与引用类型嵌套使用时,只需要记住最外围的类型是什么,根据最外面的类型来画内存图。
lazy属性和 willSet 和 didSet 方法
lazy 属性干嘛用呢,在你的这个属性占用资源较多时,你可以在声明它之前加个 lazy 修饰符,这样只有当程序用到这个属性的时候才会去创建它加载进去,提升APP性能。
重载操作符、相等操作符
- 重载操作符类似于自定义函数,只是函数名变成了操作符,需要加一些特殊的前缀(prefix)、中缀(infix)、后缀(postfix)等。
- 值相等和引用相等,===/!==是判断引用是否相等,只适用于引用类型;==/!=判断值相等。
copy下老师的代码,大家看下如何自定义操作符。
//中缀操作符
func + (left: Complex, right: Complex) -> Complex {
return Complex(real: left.real + right.real,
imag: left.imag + right.imag)
}
var c1=Complex(real: 10,imag: 20)
var c2=Complex(real: 100,imag: 200)
var c3=c1+c2
//前缀操作符
prefix func - (data: Complex) -> Complex {
return Complex(real: -data.real, imag: -data.imag)
}
var c4 = -c3
//复合赋值操作符
func += ( left: inout Complex, right: Complex) {
left = left + right
}
c1+=c2
//自定义操作符
prefix operator +++
prefix func +++ ( data: inout Complex) -> Complex {
data += data
return data
}
//值相等操作符
func == (left: Complex, right: Complex) -> Bool {
return (left.real == right.real) && (left.imag == right.imag)
}
func != (left: Complex, right: Complex) -> Bool {
return !(left == right)
}
第一周作业:
请为以下四种类型设计方式画出类型的内存模型(任何画图工具都可)。分析每种设计方案的优缺点,选出你认为最佳的实现方式,并解释为什么。
第一种实现
class Point {
var x:Int
var y:Int
}
class Rectangle
{
var leftup: Point
var width: Int
var height: Int
}
第二种实现
struct Point {
var x:Int
var y:Int
}
class Rectangle
{
var leftup: Point
var width: Int
var height: Int
}
第三种实现
class Point {
var x:Int
var y:Int
}
struct Rectangle
{
var leftup: Point
var width: Int
var height: Int
}
第四种实现
struct Point {
var x:Int
var y:Int
}
struct Rectangle
{
var leftup: Point
var width: Int
var height: Int
}
我认为引用类型嵌套值类型最优,一是它占用栈空间小,二是各个值都不会受其他值影响。
sizeOfValue and strideOfValue
二者都是测量内存大小的函数,只是后者是考虑了内存对齐,不足4bits或不足8bits自动补齐,对应32位和64位机器。