玩Swift,来自Java背景,为什么要选择Struct而不是Class?看起来它们是一样的东西,只不过Struct提供的功能更少。那为什么选择它呢?
当前回答
结构vs类
[堆栈vs堆] [值vs参考类型]
结构更可取。但是缺省情况下,Struct并不能解决所有问题。通常你会听说值类型是在堆栈上分配的,但这并不总是正确的。只有局部变量被分配到堆栈上
//simple blocks
struct ValueType {}
class ReferenceType {}
struct StructWithRef {
let ref1 = ReferenceType()
}
class ClassWithRef {
let ref1 = ReferenceType()
}
func foo() {
//simple blocks
let valueType1 = ValueType()
let refType1 = ReferenceType()
//RetainCount
//StructWithRef
let structWithRef1 = StructWithRef()
let structWithRef1Copy = structWithRef1
print("original:", CFGetRetainCount(structWithRef1 as CFTypeRef)) //1
print("ref1:", CFGetRetainCount(structWithRef1.ref1)) //2 (originally 3)
//ClassWithRef
let classWithRef1 = ClassWithRef()
let classWithRef1Copy = classWithRef1
print("original:", CFGetRetainCount(classWithRef1)) //2 (originally 3)
print("ref1:", CFGetRetainCount(classWithRef1.ref1)) //1 (originally 2)
}
*你不应该使用/依赖retainCount,因为它没有提供有用的信息
检查堆栈或堆
在编译过程中SIL(Swift中间语言)可以优化你的代码
swiftc -emit-silgen -<optimization> <file_name>.swift
//e.g.
swiftc -emit-silgen -Onone file.swift
//emit-silgen -> emit-sil(is used in any case)
//-emit-silgen Emit raw SIL file(s)
//-emit-sil Emit canonical SIL file(s)
//optimization: O, Osize, Onone. It is the same as Swift Compiler - Code Generation -> Optimization Level
在那里你可以找到alloc_stack(在堆栈上的分配)和alloc_box(在堆上的分配)
(优化级别(SWIFT_OPTIMIZATION_LEVEL)]
其他回答
许多Cocoa api需要NSObject子类,这迫使你使用class。但除此之外,你可以使用以下苹果Swift博客中的案例来决定是使用struct / enum值类型还是类引用类型。
https://developer.apple.com/swift/blog/?id=10
这个答案最初是关于结构和类之间性能的差异。不幸的是,关于我使用的测量方法有太多的争议。我把它留在下面,但请不要过多地去理解它。我认为经过这么多年,在Swift社区中,struct(以及enum)由于其简单和安全而一直是首选。
如果性能对你的应用很重要,那就自己衡量。我仍然认为大多数时候结构性能更优越,但最好的答案就像有人在评论中说的那样:这要看情况。
===旧答案===
由于结构实例是在堆栈上分配的,而类实例是在堆上分配的,因此结构有时会快得多。
但是,您应该始终自己衡量它,并根据您独特的用例进行决定。
考虑下面的例子,它演示了使用结构和类包装Int数据类型的两种策略。我使用10个重复值是为了更好地反映现实世界,其中有多个字段。
class Int10Class {
let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
init(_ val: Int) {
self.value1 = val
self.value2 = val
self.value3 = val
self.value4 = val
self.value5 = val
self.value6 = val
self.value7 = val
self.value8 = val
self.value9 = val
self.value10 = val
}
}
struct Int10Struct {
let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
init(_ val: Int) {
self.value1 = val
self.value2 = val
self.value3 = val
self.value4 = val
self.value5 = val
self.value6 = val
self.value7 = val
self.value8 = val
self.value9 = val
self.value10 = val
}
}
func + (x: Int10Class, y: Int10Class) -> Int10Class {
return IntClass(x.value + y.value)
}
func + (x: Int10Struct, y: Int10Struct) -> Int10Struct {
return IntStruct(x.value + y.value)
}
使用以下方法来衡量性能
// Measure Int10Class
measure("class (10 fields)") {
var x = Int10Class(0)
for _ in 1...10000000 {
x = x + Int10Class(1)
}
}
// Measure Int10Struct
measure("struct (10 fields)") {
var y = Int10Struct(0)
for _ in 1...10000000 {
y = y + Int10Struct(1)
}
}
func measure(name: String, @noescape block: () -> ()) {
let t0 = CACurrentMediaTime()
block()
let dt = CACurrentMediaTime() - t0
print("\(name) -> \(dt)")
}
代码可以在https://github.com/knguyen2708/StructVsClassPerformance上找到
更新(2018年3月27日):
Swift 4.0, Xcode 9.2,在iPhone 6S, iOS 11.2.6上运行Release build, Swift编译器设置为-O -全模块优化:
类版本用时2.06秒 Struct版本耗时4.17e-08秒(快了50,000,000倍)
(我不再平均多次运行,因为方差非常小,低于5%)
注意:在没有整个模块优化的情况下,差异会小很多。如果有人能指出这面旗子到底是干什么的,我会很高兴。
更新(2016年5月7日):
Swift 2.2.1, Xcode 7.3,在iPhone 6S, iOS 9.3.1上运行Release build,平均运行5次,Swift编译器设置为-O -whole-module-optimization:
类版本花费了2.159942142s struct版本耗时5.83 e -08秒(快37,000,000倍)
注意:正如有人提到的,在现实场景中,一个结构中可能会有多个字段,我已经为结构/类添加了10个字段而不是1个字段的测试。令人惊讶的是,结果变化不大。
原始结果(2014年6月1日):
(在struct/class上运行,只有1个字段,而不是10个)
在Swift 1.2、Xcode 6.3.2、iPhone 5S和iOS 8.3上运行Release版本时,平均运行超过5次
类版本花费了9.788332333s Struct版本花费0.010532942秒(快900倍)
旧结果(未知时间)
(在struct/class上运行,只有1个字段,而不是10个)
在我的MacBook Pro上发布:
类版本花费了1.10082秒 struct版本花了0.02324秒(快了50倍)
As struct are value types and you can create the memory very easily which stores into stack.Struct can be easily accessible and after the scope of the work it's easily deallocated from the stack memory through pop from the top of the stack. On the other hand class is a reference type which stores in heap and changes made in one class object will impact to other object as they are tightly coupled and reference type.All members of a structure are public whereas all the members of a class are private.
struct的缺点是不能被继承。
Structure and class are user defied data types By default, structure is a public whereas class is private Class implements the principal of encapsulation Objects of a class are created on the heap memory Class is used for re usability whereas structure is used for grouping the data in the same structure Structure data members cannot be initialized directly but they can be assigned by the outside the structure Class data members can be initialized directly by the parameter less constructor and assigned by the parameterized constructor
一些好处:
由于不可共享,自动线程安全 由于没有isa和refcount,使用更少的内存(实际上通常是堆栈分配) 方法总是静态分派的,所以可以内联(尽管@final可以为类这样做) 更容易推理(不需要“防御性复制”,这是典型的NSArray, NSString等…)出于与线程安全相同的原因
推荐文章
- swift语言中的结构与类
- 我如何在Swift连接字符串?
- 我应该如何从字符串中删除所有的前导空格?- - - - - -斯威夫特
- 接口方法的最终参数-有什么意义?
- Swift:理解// MARK
- Swift -转换为绝对值
- Swift编译器错误:“框架模块内的非模块化头”
- 从父iOS访问容器视图控制器
- 什么时候使用Struct vs. OpenStruct?
- NSRange从Swift Range?
- 我可以使用范围操作符与if语句在Swift?
- 在Swift中转换字符串为日期
- 点击按钮时如何打开手机设置?
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 编译器错误:带有Objective-C选择器的方法与前面带有相同Objective-C选择器的声明冲突