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

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


当前回答

类和结构都可以做到:

定义属性来存储值 定义提供功能的方法 被扩展 遵守协议 定义初始化 定义下标以提供对其变量的访问

唯一的类可以做到:

继承 铸字 定义deinitialisers 允许多个引用进行引用计数。

其他回答

类和结构都可以做到:

定义属性来存储值 定义提供功能的方法 被扩展 遵守协议 定义初始化 定义下标以提供对其变量的访问

唯一的类可以做到:

继承 铸字 定义deinitialisers 允许多个引用进行引用计数。

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

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"

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

这个问题似乎是重复的,但无论如何,下面的问题将回答大多数用例:

One of the most important differences between structures and classes is that structures are value types and are always copied when they are passed around in your code, and classes are reference type and are passed by reference. Also, classes have Inheritance which allows one class to inherit the characteristics of another. Struct properties are stored on Stack and Class instances are stored on Heap hence, sometimes the stack is drastically faster than a class. Struct gets a default initializer automatically whereas in Class, we have to initialize. Struct is thread safe or singleton at any point of time.

而且, 要总结结构和类之间的区别,有必要了解值类型和引用类型之间的区别。

在复制值类型时,它将从其中复制所有数据 你要复制到新变量中的东西。它们是分开的 事物和改变一个并不影响另一个。 复制引用类型时,新变量引用 与你要复制的东西相同的内存位置。这意味着 改变一个会改变另一个因为它们都指向 相同的内存位置。 下面的示例代码可以作为参考。

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

如果你仔细看苹果手册,你会看到这部分: 结构和枚举是值类型

在本节中,你会看到:

“​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.

当然,传递结构类型可以减少大量错误的可能性,但它们也会降低程序的速度,这取决于所包含的类型。