返回

结构体与类的本质区别

IOS

结构体与类:深入理解其本质区别

值类型与引用类型:存储方式之别

结构体和类在 Swift 中定义自定义类型的两种基本方式,它们的首要区别在于存储方式。结构体是值类型,这意味着它们的副本存储在栈内存中。当您赋值或传递结构体时,其值会被复制到新的内存位置。

另一方面,类是引用类型,这意味着它们存储在堆内存中。当您赋值或传递类时,您实际上只是在传递指向该对象在堆中的内存位置的引用。这意味着对引用类型的任何更改都会反映在原始对象上。

内存管理:自动销毁与手动释放

值类型和引用类型的存储方式对内存管理产生了重大影响。对于值类型,由于它们存储在栈中,因此在它们超出作用域时会被自动销毁。这意味着您不必担心手动释放值类型的内存。

对于引用类型,由于它们存储在堆中,因此您必须手动释放它们的内存。如果不这样做,将导致内存泄漏,这可能会降低应用程序的性能并最终导致崩溃。

初始化:默认值与显式初始化

结构体和类在初始化方面也有所不同。结构体有默认的成员初始化器,该初始化器会将所有成员初始化为其默认值。类没有默认的成员初始化器,因此您必须显式地初始化所有存储属性。

此外,结构体可以定义自定义初始化器,这些初始化器可以接受参数并执行额外的初始化逻辑。类也可以定义自定义初始化器,但它们还可以定义析构器,这些析构器将在对象超出作用域时被调用以释放其资源。

其他差异:不变性、值传递与引用传递

除了上面讨论的差异之外,结构体和类之间还存在一些其他差异:

  • 不变性: 结构体是不可变的,这意味着您不能修改其属性。类是可变的,这意味着您可以修改其属性。
  • 值传递与引用传递: 结构体可以作为值传递,而类只能作为引用传递。
  • 轻量级数据与复杂对象: 结构体更适合表示轻量级、不可变的数据,而类更适合表示复杂、可变的对象。

何时使用结构体与类:权衡选择

在决定何时使用结构体或类时,请考虑以下准则:

  • 轻量级、不可变的数据: 使用结构体。
  • 复杂、可变的对象: 使用类。
  • 值传递: 使用结构体。
  • 引用传递: 使用类。

代码示例:展示结构体与类的差异

struct Point {
  let x: Int
  let y: Int
}

class Person {
  var name: String
  var age: Int
  
  init(name: String, age: Int) {
    self.name = name
    self.age = age
  }
}

var point1 = Point(x: 10, y: 20)
var point2 = point1

point2.x = 30

print(point1.x) // 输出:10
print(point2.x) // 输出:30

var person1 = Person(name: "John", age: 30)
var person2 = person1

person2.name = "Mary"

print(person1.name) // 输出:Mary
print(person2.name) // 输出:Mary

在上面的示例中,Point 是一个结构体,它的副本被传递给了 point2。对 point2 的更改不会影响 point1,因为结构体是值类型。另一方面,Person 是一个类,它的引用被传递给了 person2。对 person2 的更改也会影响 person1,因为类是引用类型。

常见问题解答

1. 为什么结构体是不可变的,而类是可变的?

结构体是值类型,这意味着它们在内存中是按值存储的。对结构体进行任何更改都会创建一个新副本,从而保持原始结构体的不变性。另一方面,类是引用类型,这意味着它们在内存中按引用存储。对类进行更改将直接影响原始对象,因此类是可变的。

2. 什么时候应该使用结构体,什么时候应该使用类?

一般来说,当您要表示轻量级、不可变的数据时,应该使用结构体。当您要表示复杂、可变的对象时,应该使用类。

3. 结构体和类之间还有什么其他差异?

除了本文中讨论的差异之外,结构体和类之间还有其他一些差异,例如:

  • 值语义 vs 引用语义: 结构体遵循值语义,这意味着对它们的更改不会影响原始结构体。类遵循引用语义,这意味着对它们的更改将影响原始对象。
  • 内存布局: 结构体在内存中连续存储其成员,而类在内存中存储指向其成员的指针。
  • 性能: 结构体通常比类具有更好的性能,因为它们不需要指针开销。

4. 结构体和类的设计模式是什么?

结构体通常用于表示简单的值类型,例如点、大小或颜色。类通常用于表示复杂的对象,例如用户、产品或订单。

5. Swift 中的枚举如何与结构体和类进行比较?

枚举也是一种定义自定义类型的基本方式,但它们与结构体和类有不同的用途。枚举用于表示一组有限的、相关的值。它们是值类型,不能存储存储属性或定义方法。