Swift - 值类型与引用类型的初步探究

前言

swift中的结构体和类在组成和功能上具有一定的相似性、两者都可以含有成员属性、成员方法用于数据存储和功能性模块封装。往往造成不知如何对二者进行区分和使用

值类型概念和引用类型概念

值类型的概念:值类型是指在系统进行标准的复制后,被复制的对象与复制出的对象之间完完全全的不存在任何关系,彼此之间具有绝对性的独立、此类型的数据被称为值类型(与OC中的深拷贝相同)

引用类型的概念:引用类型是指在系统进行标准复制后,被复制对象与复制出的对象之间具有底层的共有关系,也就是说两者功用的是同一个底层资源。此类型被称为引用类型

值类型与引用类型的根本区别在于其存储区域的不同

swift中的数据存储分为栈区与堆区,栈区存储值类型,堆区存储自定义类型与值类型数据和代码。这里我们因为OC中的一个例子如下:

/*引用类型数据结构*/
@interface SomeClass : NSObject 
@property int number;
@end
@implementation SomeClass
@end

/*值类型数据结构*/
struct SomeStruct {
    int number;
};


SomeClass *reference = [[SomeClass alloc] init];
reference.number = 42;
SomeClass *reference2 = reference;
reference.number = 43;
NSLog(@"The number in reference2 is %d", reference2.number);
The number in reference2 is 43



struct SomeStruct value = {};
value.number = 42;
struct SomeStruct value2 = value;
value.number = 43;
NSLog(@"The number in value2 is %d", value2.number);
The number in value2 is 42

造成以上结果的差异主要在于存储变量或者对象的空间区域的不同。Class类首先通过alloc init 方法在堆区域创建一个内存空间存放实例属性和代码。然后在把创建的实例引用赋值给一个变量类型存储在栈区,当通过引用时就通过栈区的引用地址区堆区查找实例对象内容。因此赋值一个引用在底层上是对底层进行修改的。

结构体类是值引用类型,可以存储在栈区或者堆区,当存储在栈区或者堆区时其返回的都是数据内容本身,通过对数据本身的赋值也就是为其底层进行数据赋值,其结果是产生一份独立性的数据

值类型与引用类型的嵌套

值类型嵌套值类型:值类型的嵌套会扩大存储区域,内部值是外部值的一部分会产生一个全新的值类型

struct baseStruct {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

/*值类型嵌套值类型*/
struct numberStruct {
    var base:baseStruct!
    var number:Int = 20
}

let num:numberStruct = numberStruct(base: baseStruct(number: 10, numDes: "baseStruct"), number: 20)
 print("num.num:\(num.number), num.base.name:\(num.base.number)")
        
        
 var num1:numberStruct = num
 num1.number = 200
 num1.base.number = 100
 print("num1.num:\(num1.number), num1.base.name:\(num1.base.number)")

 print("num.num:\(num.number), num.base.name:\(num.base.number)")

打印结果
num.num:20, num.base.name:10
num1.num:200, num1.base.name:100
num.num:20, num.base.name:10

引用类型嵌套引用类型:引用类型的嵌套可以理解为一个全新的引用类型

class baseClass {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

struct baseStruct {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

class Student {
    var baseCl:baseClass = baseClass.init()
    var baseStru:baseStruct = baseStruct.init()
    func printDes() -> Void {
        print("baseCL\(self.baseCl.number, self.baseCl.numDes) baseStru:\(self.baseStru.number, self.baseStru.numDes)")
    }
}

let stu1:Student = Student.init()
stu1.baseCl.number = 10
stu1.baseCl.numDes = "baseClass"
stu1.baseStru.number = 20
stu1.baseStru.numDes = "baseStruct"
stu1.printDes()


let stu2:Student = stu1
stu2.baseCl.number = 100
stu2.baseCl.numDes = "baseClass*10"
stu2.baseStru.number = 200
stu2.baseStru.numDes = "baseStruct*10"
stu2.printDes()

stu1.printDes()
baseCL(10, "baseClass") baseStru:(20, "baseStruct")
baseCL(100, "baseClass*10") baseStru:(200, "baseStruct*10")
baseCL(100, "baseClass*10") baseStru:(200, "baseStruct*10")

引用类型嵌套值类型:引用类型嵌套值类型产生一个全新的引用类型

class baseClass {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

struct baseStruct {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

class Student {
    var baseCl:baseClass = baseClass.init()
    var baseStru:baseStruct = baseStruct.init()
    func printDes() -> Void {
        print("baseCL\(self.baseCl.number, self.baseCl.numDes) baseStru:\(self.baseStru.number, self.baseStru.numDes)")
    }
}

let stu1:Student = Student.init()
stu1.baseCl.number = 10
stu1.baseCl.numDes = "baseClass"
stu1.baseStru.number = 20
stu1.baseStru.numDes = "baseStruct"
stu1.printDes()


let stu2:Student = stu1
stu2.baseCl.number = 100
stu2.baseCl.numDes = "baseClass*10"
stu2.baseStru.number = 200
stu2.baseStru.numDes = "baseStruct*10"
stu2.printDes()

stu1.printDes()
baseCL(10, "baseClass") baseStru:(20, "baseStruct")
baseCL(100, "baseClass*10") baseStru:(200, "baseStruct*10")
baseCL(100, "baseClass*10") baseStru:(200, "baseStruct*10")

值类型嵌套引用类型:当值类型嵌套引用类型时情况有些复杂,他产生的对象类型时一个变异的值类型!值类型中的非引用类型会发生全新的拷贝,引用类型则遵循引用类型的拷贝规则。总结起来就是变异的值类型依然会产生一个最新的拷贝副本,但是如果其中有引用属性时则拷贝的引用属性仅仅时拷贝的一个引用指针并不是引用内容

struct baseStruct {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

class baseClass {
    var number:Int = 10
    var numDes:String = "baseStruct"
}

/*值类型嵌套值类型*/
struct numberStruct {
    var base:baseStruct!
    var number:Int = 20
}


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        /*值类型嵌套引用类型*/
        var stu1:numberExample = numberExample.init()
        stu1.baseCl.number = 10
        stu1.baseCl.numDes = "baseClass"
        stu1.baseStru.number = 20
        stu1.baseStru.numDes = "baseStruct"
        stu1.printDes()
        
        
        var stu2:numberExample = stu1
        stu2.baseCl.number = 100
        stu2.baseCl.numDes = "baseClass*10"
        stu2.baseStru.number = 200
        stu2.baseStru.numDes = "baseStruct*10"
        stu2.printDes()
        
        stu1.printDes()
        

    }


baseCL(10, "baseClass") baseStru:(20, "baseStruct")
baseCL(100, "baseClass*10") baseStru:(200, "baseStruct*10")
baseCL(100, "baseClass*10") baseStru:(20, "baseStruct")



结论:在swift中,无论你何时去拷贝一个值类型,则都会产生一个全新的副本,拷贝一个引用类型则产生一份全新的引用,其底层不发声任何变化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值