来自Apple的书 “结构和类之间最重要的区别之一是结构总是在代码中传递时被复制,但是类通过引用传递。”
任何人都可以让我理解这意味着什么,对我而言,类和结构似乎是一样的。
答案 0 :(得分:441)
以下是class
的示例。请注意,如果更改名称,则更新两个变量引用的实例。 <{1}}现在Bob
,Sue
被引用的所有地方。
Bob
现在使用class SomeClass {
var name: String
init(name: String) {
self.name = name
}
}
var aClass = SomeClass(name: "Bob")
var bClass = aClass // aClass and bClass now reference the same instance!
bClass.name = "Sue"
println(aClass.name) // "Sue"
println(bClass.name) // "Sue"
,我们看到值被复制,每个变量都保留了它自己的一组值。当我们将名称设置为struct
时,Sue
中的Bob
结构不会发生变化。
aStruct
因此,为了表示有状态的复杂实体,struct SomeStruct {
var name: String
init(name: String) {
self.name = name
}
}
var aStruct = SomeStruct(name: "Bob")
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.name = "Sue"
println(aStruct.name) // "Bob"
println(bStruct.name) // "Sue"
非常棒。但是对于仅仅是测量或相关数据位的值,class
更有意义,因此您可以轻松地复制它们并使用它们进行计算或修改值而不用担心副作用。
答案 1 :(得分:55)
类和结构都可以:
只有班级才能做到:
答案 2 :(得分:29)
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
类是引用类型。这意味着,如果您将一个类的实例分配给一个变量,它只会将引用保存到实例,而不包含副本。
答案 3 :(得分:7)
以上答案是正确的我希望我的回答可以帮助那些不理解上述答案的人。
在Swift中有两种类型的对象
它们之间的主要区别是
例如,这里的代码可以很好地理解。
struct SomeStruct {
var a : Int;
init(_ a : Int) {
self.a = a
}
}
class SomeClass {
var a: Int;
init(_ a: Int) {
self.a = a
}
}
var x = 11
var someStruct1 = SomeStruct(x)
var someClass1 = SomeClass(x)
var someStruct2 = someStruct1
var someClass2 = someClass1
someClass1.a = 12
someClass2.a // answer is 12 because it is referencing to class 1 property a
someStruct1.a = 14
someStruct2.a // answer is 11 because it is just copying it not referencing it
这是主要区别,但我们也存在分歧。
<强>类强>
<强> STRUCT 强>
答案 4 :(得分:6)
这个问题似乎是重复的,但无论如何,以下内容将回答大部分用例:
结构和类之间最重要的区别之一 是结构是值类型,并始终复制它们 在代码中传递,类是引用类型和 通过引用传递。
此外,类具有继承,允许一个类继承 另一个人的特征。
结构属性存储在Stack上,并存储Class实例 因此,有时堆栈比a快得多 类。
Struct自动获取默认初始值设定项,而在Class中,我们 必须初始化。
Struct在任何时候都是线程安全的或单例的。
而且, 总结结构和类之间的区别,有必要理解值和引用类型之间的区别。
// sampleplayground.playground
class MyClass {
var myName: String
init(myName: String){
self.myName = myName;
}
}
var myClassExistingName = MyClass(myName: "DILIP")
var myClassNewName = myClassExistingName
myClassNewName.myName = "John"
print("Current Name: ",myClassExistingName.myName)
print("Modified Name", myClassNewName.myName)
print("*************************")
struct myStruct {
var programmeType: String
init(programmeType: String){
self.programmeType = programmeType
}
}
var myStructExistingValue = myStruct(programmeType: "Animation")
var myStructNewValue = myStructExistingValue
myStructNewValue.programmeType = "Thriller"
print("myStructExistingValue: ", myStructExistingValue.programmeType)
print("myStructNewValue: ", myStructNewValue.programmeType)
输出:
Current Name: John
Modified Name John
*************************
myStructExistingValue: Animation
myStructNewValue: Thriller
答案 5 :(得分:3)
如果你在苹果手册中看得更远,你会看到这一部分: “结构和枚举是价值类型”
在本节中,您将看到:
“让hd =分辨率(宽度:1920,高度:1080)var cinema = hd此示例声明一个名为hd的常量并设置它 到使用full的宽度和高度初始化的Resolution实例 高清视频(1920像素宽,1080像素高)。
然后声明一个名为cinema的变量并将其设置为当前变量 高清的价值。因为Resolution是一个结构,是现有的副本 实例,并将此新副本分配给电影院。即使 高清和电影现在有相同的宽度和高度,它们是两个 幕后完全不同的实例。
接下来,将影院的宽度属性修改为宽度 用于数字电影放映的略宽2K标准(2048 像素宽,1080像素高):
cinema.width = 2048检查电影院的宽度属性 它确实变成了2048:
println(&#34;影院现在(影院。宽度)像素宽&#34;)// 打印&#34;影院现在是2048像素宽但是,宽度属性 原始的高清实例仍然具有1920年的旧值:
println(&#34; hd仍然是(高清宽度)像素宽&#34;)//打印&#34;高清 仍然是1920像素宽“
当影院获得当前hd值时,值存储在hd中 被复制到新的电影院实例中。最终结果是两个 完全独立的实例,恰好包含相同的实例 数值。因为它们是单独的实例,所以设置宽度 电影到2048的影响不会影响存储在高清中的宽度。“
摘自:Apple Inc.“The Swift Programming Language。”iBooks。 https://itun.es/us/jEUH0.l
这是结构和类之间的最大区别。复制结构并引用类。
答案 6 :(得分:1)
通常(在大多数编程语言中),对象是存储在堆上的数据块,然后是这些块的引用(通常是指针),包含用于访问这些数据块的name
。此机制允许通过复制其引用(指针)的值来共享堆中的对象。这不是基本数据类型(如整数)的情况,这是因为创建引用所需的内存几乎与对象相同(在本例中为整数值)。因此,在大对象的情况下,它们将作为值传递而不是作为参考。
Swift使用struct来提高性能,即使使用String和Array对象也是如此。
答案 7 :(得分:1)
这是一个精确显示struct和class之间差异的例子。
struct Radio1{
var name:String
// init(name:String) {
// self.name = name
// }
}
struct Car1{
var radio:Radio1?
var model:String
}
var i1 = Car1(radio: Radio1(name:"murphy"),model:"sedan")
var i2 = i1
//since car instance i1 is a struct and
//this car has every member as struct ,
//all values are copied into i2
i2.radio?.name //murphy
i2.radio = Radio1(name: "alpha")
i2.radio?.name //alpha
i1.radio?.name //murphy
//since Radio1 was struct ,
//values were copied and thus
// changing name of instance of Radio1 in i2
//did not bring change in i1
class Radio2{
var name:String
init(name:String) {
self.name = name
}
}
struct Car2{
var radio:Radio2?
var model:String
}
var i3 = Car2(radio: Radio2(name:"murphy"),model:"sedan")
//var radioInstance = Radio2(name: "murphy")
//var i3 = Car2(radio: radioInstance,model:"sedan")
var i4 = i3
//since i3 is instance of struct
//everything is copied to i4 including reference of instance of Radio2
//because Radio2 is a class
i4.radio?.name //murphy
i4.radio?.name="alpha"
i4.radio?.name //alpha
i3.radio?.name //alpha
//since Radio2 was class,
//reference was copied and
//thus changing name of instance
//of Radio2 in i4 did bring change in i3 too
//i4.radio?.name
//i4.radio = Radio2(name: "alpha")
//i4.radio?.name
//
//i3.radio?.name
答案 8 :(得分:1)
为了理解Structs和Classes之间的区别,我们需要知道值和引用类型之间的主要区别。结构是值类型,这意味着它们上的每个更改都只会修改该值,类是引用类型,引用类型中的每个更改都将修改在该内存或引用位置分配的值。例如:
让我们从一个类开始,这个类符合Equatable只是为了能够比较实例,我们创建一个名为pointClassInstanceA
的实例和其他名为pointClassInstanceB
的实例,我们将A类分配给B类,现在断言说他们是一样的......
class PointClass: Equatable {
var x: Double
var y: Double
init(x: Double, y: Double) {
self.x = x
self.y = y
}
static func == (lhs: PointClass, rhs: PointClass) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
var pointClassInstanceA = PointClass(x: 0, y: 0)
var pointClassInstanceB = pointClassInstanceA
assert(pointClassInstanceA==pointClassInstanceB)
pointClassInstanceB.x = 10
print(pointClassInstanceA.x)
//this prints 10
好的,这里发生了什么,如果我们只更改了pointsClassInstanceB的x值,它还改变了pointClassInstanceA的x值?好吧,这显示了引用类型如何工作,当我们分配实例A时,作为实例B的值,然后我们修改其中一个的X,它将改变两个X,因为它们共享相同的引用,并且改变了它的值参考
让我们做同样的事情但是使用结构
struct PointStruct: Equatable {
var x: Double
var y: Double
init(x: Double, y: Double) {
self.x = x
self.y = y
}
static func == (lhs: PointStruct, rhs: PointStruct) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
var pointStructInstanceA = PointStruct(x: 0, y: 0)
var pointStructInstanceB = pointStructInstanceA
assert(pointStructInstanceA==pointStructInstanceB)
pointStructInstanceB.x = 100
print(pointStructInstanceA.x)
//this will print 0
我们的类与我们的类基本相同,但现在你可以看到,当你打印pointStructInstanceA的x值时,它没有改变,这是因为值类型的工作方式不同,其中一个实例的每个更改都有所不同将是“独立的”,不会影响另一方。
Swift建议使用更多的值类型,你可以告诉他们的库是基于结构的,以避免引用类型带来的问题,比如无意中修改了值等。结构是继续使用Swift的方法。 希望它有所帮助。答案 9 :(得分:1)
Value Type
:
value type
时,将创建新的数据副本(实际上使用了写时复制(COW)机制)。 Reference Type
:
reference type
时,将创建对原始实例的新引用(复制实例的地址)。 Value type
默认使用 。 Value type
的最大优点是通常它们是thread safe
对于Reference type
,它们可以被继承,deinit()
,可以通过引用===
比较实例,Objective-C
的互操作性,因为Value Type
是在Swift中引入的
答案 10 :(得分:0)
Alreday有很多关于此的文章,我想在那里加一个类比。希望在此之后你永远不会怀疑: 底线: 类通过引用传递,而结构通过值传递。
假设您正在与朋友分享Google文档资料表。现在,如果他改变了任何内容,您还会看到谷歌文档的更改,意味着您的副本也会受到影响。 这基本上是&#34; 通过引用传递&#34;。
但是假设您的计算机中保存了.XLS文件。您将该文件提供给您的朋友。现在,如果他对该文件进行任何更改,您的文件将不会被搞乱,因为您有自己的副本。 这基本上是&#34; 通过值传递&#34;。 你已经有多个简单的程序在swift playgrounds中检查这个类比。
答案 11 :(得分:0)
1.structure is value type.
= > when we assign structure variable to other variable or pass as parameter to function, it creates separate/new copy => so that changes made on one variable does not reflect on another.[We can say like **call by value** concept]
Example :
struct DemoStruct
{
var value: String
init(inValue: String)
{
self.value = inValue
}
}
var aStruct = DemoStruct(inValue: "original")
var bStruct = aStruct // aStruct and bStruct are two structs with the same value! but references to diff location`enter code here`
bStruct.value = "modified"
print(aStruct.value) // "original"
print(bStruct.value) // "modified"
2.class is reference type.
= > when we assign structure variable to other variable or pass as parameter to function, it **does not** creates separate/new copy => so that changes made on one variable does not reflect on another.[We can say like **call by reference** concept]
Example:
class DemoClass
{
var value: String
init(inValue: String)
{
self.value = inValue
}
}
var aClass = DemoClass(inName: "original")
var bClass = aClass // aClass and bClass now reference the same instance!
bClass.value = "modified"
print(aClass.value) // "modified"
print(bClass.value) // "modified"
答案 12 :(得分:0)
Value Type
:复制值类型时(即在将其分配,初始化或传递给函数时),每个实例保留数据的唯一副本。如果您更改一个实例,其他实例也不会更改。
Reference Type
:复制引用类型时,每个实例共享数据。引用本身被复制,但不是引用的数据。当您更改一个时,另一个也会更改。
建议默认使用struct。
对简单数据类型使用结构。考虑一下您想在代码中传递的数据库对象,例如NewsItem,Task或User。由于它们定义非常明确,并且通常不需要适应对象之间的复杂关系,因此使用结构更简单。
在多线程环境中(例如,在不同线程中打开了数据库连接),结构更安全。可以将它们从一个线程复制到另一个线程,而不会出现争用情况或死锁的风险。除非故意使类成为线程安全的,否则类没有这种固有的安全性。
当结构的属性也大多是值类型(例如String)时,将它们包装在结构而不是类中是很有意义的。
如果需要班级的特定功能,建议使用班级。
在let
上使用struct
会使该对象成为常数。它不能更改或重新分配,其变量也不能。创建为var
的结构可以更改其变量。
由于classes
是引用对象,let
和var
之间的唯一区别是能够将变量重新分配给同一类型的不同类。 let
和var
关键字不影响更改类中变量的能力。
标记为mutating
的函数会更改内部属性值。突变功能仅在structs
上存在,并且只能在创建为structs
的{{1}}上使用。
由于var
是值类型,因此它们按值传递。这意味着它们的内容在传递给函数时将被复制。如果需要在函数内部修改struct变量并将其值保留在函数范围之外,则可以将struct变量标记为structs
参数。