摘自苹果书籍 “结构和类之间最重要的区别之一是,结构在代码中传递时总是被复制,但类是通过引用传递的。”

有人能帮我理解一下这是什么意思吗?对我来说,类和结构似乎是一样的。


当前回答

下面是一个类的例子。请注意,当名称更改时,两个变量引用的实例将如何更新。鲍勃现在是苏了,所有提到鲍勃的地方都是这样。

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"

现在使用结构体,我们看到值被复制,每个变量保留自己的值集。当我们将名称设置为Sue时,aStruct中的Bob结构体不会被更改。

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"

所以对于表示有状态的复杂实体来说,类是非常棒的。但是对于仅仅是测量值或相关数据位的值,结构体更有意义,这样您可以轻松地复制它们并使用它们计算或修改值,而不用担心副作用。

其他回答

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

类是引用类型。这意味着如果将类的一个实例赋值给一个变量,它将只保存对该实例的引用,而不是副本。

下面是一个类的例子。请注意,当名称更改时,两个变量引用的实例将如何更新。鲍勃现在是苏了,所有提到鲍勃的地方都是这样。

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"

现在使用结构体,我们看到值被复制,每个变量保留自己的值集。当我们将名称设置为Sue时,aStruct中的Bob结构体不会被更改。

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"

所以对于表示有状态的复杂实体来说,类是非常棒的。但是对于仅仅是测量值或相关数据位的值,结构体更有意义,这样您可以轻松地复制它们并使用它们计算或修改值,而不用担心副作用。

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和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

已经有很多关于这方面的文章了,我想在这里加一个类比。希望你看完这篇文章后,心中永远不会再有疑虑: 底线: 类通过引用传递,而结构通过值传递。

假设你和你的朋友共享一个谷歌文档表。现在,如果他改变了其中的任何内容,你也会在谷歌文档上看到变化,这意味着你的副本也受到了影响。 这基本上是“通过引用传递”。

但假设,如果你有一个。xls文件保存在你的机器。你把那份文件交给你的朋友。现在,如果他在那个文件中做了任何更改,你的文件也不会被打乱/影响,因为你有自己的副本。 这基本上就是“按值传递”。 你有多个简单的程序已经在那里检查这个类比在快速操场。