摘自苹果书籍 “结构和类之间最重要的区别之一是,结构在代码中传递时总是被复制,但类是通过引用传递的。”
有人能帮我理解一下这是什么意思吗?对我来说,类和结构似乎是一样的。
摘自苹果书籍 “结构和类之间最重要的区别之一是,结构在代码中传递时总是被复制,但类是通过引用传递的。”
有人能帮我理解一下这是什么意思吗?对我来说,类和结构似乎是一样的。
当前回答
斯威夫特类型
命名类型或标称类型或有名称的类型 复合类型或非名义类型或没有名称的类型
值类型是一种类型,其值在赋值给变量或常量、传递给函数或从函数返回时被复制。(as and is检查构造的副本)
当引用类型被赋值给变量或常量,或者被传递给函数时,引用类型不会被复制
值类型:
Struct, Enum[About],元组 struct String, struct Array(Set, Dictionary)
(objective - c int…)
字符串,内置集合值类型包含对堆的内部引用,以管理它的大小
当您分配或传递值类型时,将创建数据的新副本。copy on write - COW机制用于某些特定的类(如Collections(Array, Dictionary, Set))[About],并进行了一些优化,例如在修改对象时创建副本。对于自定义类型,您应该自己支持COW 当你修改一个实例时,它只在局部起作用。 如果Value为局部变量,则使用堆栈内存[关于]
引用类型: 类,函数
(Objective-C所有其他)
使用ARC
当你分配或传递引用类型时,一个新的引用将被创建到原始实例(实例的地址被复制)。 当您修改一个实例时,它会产生全局影响,因为该实例可以被指向它的任何引用共享和访问。 通常使用堆内存[大约]
建议默认为“type”。Value类型的最大优点是它们通常是线程安全的
参考类型
它们可以遗传, 可以使用Deinit (), 通过引用===比较实例, Objective-C互操作性,因为值类型是在Swift中引入的。
[堆栈vs堆] [let vs var, class vs struct] [类别vs结构]
在结构和类之间选择 类型 类和结构
其他回答
如果你仔细看苹果手册,你会看到这部分: 结构和枚举是值类型
在本节中,你会看到:
“let hd = Resolution(width: 1920, height: 1080) var cinema = hd This example declares a constant called hd and sets it to a Resolution instance initialized with the width and height of full HD video (1920 pixels wide by 1080 pixels high). It then declares a variable called cinema and sets it to the current value of hd. Because Resolution is a structure, a copy of the existing instance is made, and this new copy is assigned to cinema. Even though hd and cinema now have the same width and height, they are two completely different instances behind the scenes. Next, the width property of cinema is amended to be the width of the slightly-wider 2K standard used for digital cinema projection (2048 pixels wide and 1080 pixels high): cinema.width = 2048 Checking the width property of cinema shows that it has indeed changed to be 2048: println("cinema is now (cinema.width) pixels wide") // prints "cinema is now 2048 pixels wide However, the width property of the original hd instance still has the old value of 1920: println("hd is still (hd.width) pixels wide") // prints "hd is still 1920 pixels wide” When cinema was given the current value of hd, the values stored in hd were copied into the new cinema instance. The end result is two completely separate instances, which just happened to contain the same numeric values. Because they are separate instances, setting the width of cinema to 2048 doesn’t affect the width stored in hd.” Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
这是结构体和类之间最大的区别。复制结构,引用类。
正如许多人已经指出复制结构体和类的区别一样,这可以从它们在c语言中的来源来理解,像这样的结构体
struct A {
let a: Int
let c: Bool
}
在func父对象或结构体的局部内存中,它将是这样的
64bit for int
8 bytes for bool
现在
class A {
let a: Int
let c: Bool
}
而不是存储在本地内存或结构或类中的数据内容,它将是一个单一指针
64bit address of class A instance
当你复制这两个时,很容易看出为什么会有区别,复制第一个,你复制了64位的int和8位的bool,复制第二个,你复制了64位的地址到A类的实例,你可以有同一个内存地址的多个副本,都指向同一个实例,但结构体的每个副本都将是它自己的副本。
现在事情变得复杂了因为你可以把这两个混合起来
struct A {
let a: ClassA
let c: Bool
}
你的记忆会是这样的
64bit address of class A instance
8 bytes for bool
This is a problem because even though you have multiple copies of the struct in your program, they all have a copy to the same object ClassA, this means just like multiples reference to instance ClassA you pass around have to have a reference count kept of how many reference to the object exists to know when to delete them, you program can have multiple references to struct A that need to keep a reference count to their ClassA instances, this can be time consuming if your struct has a lot of classes in them, or the structs it contains has lots of classes in them, now when you copy your struct, the compiler has to generate code that goes through every single class instance referenced in your struct and substructs, and increment there reference count to keep track of how many references there are. This can make classes much faster to pass around as you just need to copy its single address, and it won't need to increase the reference count of any of its children because it want reduce the reference count of any child it contains until its own reference count reaches 0.
The thing gets even more complicated with some Apple struct types, that they actually have object types in them, the good thing about data that is reference to, is it can be stored in memory and be lengthened and contractor at will and they can be very large, unlike data stored on local stack, so types like String, Array, Set, Dictionary though they act like struct and will even make a duplicate of there internal data if you try to modify them so you don't change all occurrence, there data still has to be reference counted and so a struct containing a lots of these types can still be slow, because the internal data for each one has to be retained.
当然,传递结构类型可以减少大量错误的可能性,但它们也会降低程序的速度,这取决于所包含的类型。
Usually (in most programming languages), objects are blocks of data that are stored on heap, and then a reference (normally a pointer) to these blocks, contains a name is using to access these blocks of data. This mechanism allows sharing objects in the heap by copying the value of their references (pointers). This is not the case of basic data types such as Integers, and that is because the memory needed to create a reference is almost the same as the object (in this case integer value). Thus, they will be passed as values not as a reference in the case of large objects.
Swift使用struct来提高String和Array对象的性能。
这是一本很好的读物
Struct是值类型。这意味着,如果你将结构的实例复制到另一个变量,它只是复制到变量。
值类型示例
struct Resolution {
var width = 2
var height = 3
}
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd //assigning struct instance to variable
println("Width of cinema instance is \(cinema.width)")//result is 1920
println("Width of hd instance is \(hd.width)")//result is 1920
cinema.width = 2048
println("Width of cinema instance is \(cinema.width)")//result is 2048
println("Width of hd instance is \(hd.width)")//result is 1920
类是引用类型。这意味着如果将类的一个实例赋值给一个变量,它将只保存对该实例的引用,而不是副本。
已经有很多关于这方面的文章了,我想在这里加一个类比。希望你看完这篇文章后,心中永远不会再有疑虑: 底线: 类通过引用传递,而结构通过值传递。
假设你和你的朋友共享一个谷歌文档表。现在,如果他改变了其中的任何内容,你也会在谷歌文档上看到变化,这意味着你的副本也受到了影响。 这基本上是“通过引用传递”。
但假设,如果你有一个。xls文件保存在你的机器。你把那份文件交给你的朋友。现在,如果他在那个文件中做了任何更改,你的文件也不会被打乱/影响,因为你有自己的副本。 这基本上就是“按值传递”。 你有多个简单的程序已经在那里检查这个类比在快速操场。