关于Swift是否保证类和结构中字段的存储顺序?和swift存储属性的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于11.Swift中的类和结构体、5.6类和结构两个类型的比较[Swift
关于Swift是否保证类和结构中字段的存储顺序?和swift 存储属性的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于11.Swift 中的类和结构体、5.6 类和结构两个类型的比较 [Swift原创教程]、C 11:unordered_map / set是否保证遍历顺序为插入顺序?、Elasticsearch是否保持多值字段的顺序?等相关知识的信息别忘了在本站进行查找喔。
本文目录一览:- Swift是否保证类和结构中字段的存储顺序?(swift 存储属性)
- 11.Swift 中的类和结构体
- 5.6 类和结构两个类型的比较 [Swift原创教程]
- C 11:unordered_map / set是否保证遍历顺序为插入顺序?
- Elasticsearch是否保持多值字段的顺序?
Swift是否保证类和结构中字段的存储顺序?(swift 存储属性)
在C语言中,在结构中定义字段的顺序是在内存中实例化它们的顺序。考虑到内存对齐,以下结构在内存中的大小将为8个字节,如图所示,但是如果将字段反转,则只有6个字节,因为不需要任何对齐填充。
struct s { int32_t a; /* 2 bytes of padding to align a 64 bit integer */ int64_t b;}
这种顺序保证存在于C结构,C ++类(和结构)和Objective-C类中。
Swift类和结构中的字段是否同样保证了存储顺序?或者(鉴于该语言不支持与列出的其他指针相同的指针),编译器是否在编译时为您最佳地重新安排了指针?
答案1
小编典典是的,结构元素在内存中的顺序就是它们声明的顺序。详细信息可以在“
类型布局”
(已添加重点)中找到。但是请注意使用“当前”,因此在以后的Swift版本中可能会发生变化:
脆弱的结构和元组布局
结构和元组 当前 共享相同的布局算法,在编译器实现中称为“通用”布局算法。算法如下:
- 以0的大小和1的对齐方式开始。
- 以元组的元素顺序或结构的 var声明顺序 遍历字段。对于每个字段:
- 通过四舍五入到字段的对齐方式来更新大小,即将其增大到大于或等于大小的最小值,并且可以被字段的对齐方式整除。
- 将字段的偏移量分配给size的当前值。
- 通过添加字段的大小来更新大小。
- 将对齐方式更新为最大对齐方式和字段的对齐方式。
- 最终大小和对齐方式是聚合的大小和对齐方式。该类型的跨度是将最终大小四舍五入以对齐。
填充/对齐方式与C不同:
请注意,这与C或LLVM的常规布局规则不同,因为大小和跨度是不同的。C布局要求将嵌入式结构的大小填充为其对齐方式,并且在那里不进行任何布局,而Swift布局允许外部结构在内部结构的尾部填充中布局字段,并允许对齐。
仅当从C 导入 结构时,才能保证它具有相同的内存布局。Apple的Joe Groff在[swift-
users]上写道:将
C语义映射到Swift
如果您依赖于特定的布局,则应该在C中定义该结构并将其导入到Swift中。
而后来在讨论:
您可以保留在C中定义的结构并将其导入Swift。 Swift将尊重C的布局。
例:
struct A { var a: UInt8 = 0 var b: UInt32 = 0 var c: UInt8 = 0}struct B { var sa: A var d: UInt8 = 0}// Swift 2:print(sizeof(A), strideof(A)) // 9, 12print(sizeof(B), strideof(B)) // 10, 12// Swift 3:print(MemoryLayout<A>.size, MemoryLayout<A>.stride) // 9, 12print(MemoryLayout<B>.size, MemoryLayout<B>.stride) // 10, 12
这var d: UInt8
是在的尾部填充中布置的var sa: A
。如果您在C中定义相同的结构
struct CA { uint8_t a; uint32_t b; uint8_t c;};struct CB { struct CA ca; uint8_t d;};
然后将其导入到Swift
// Swift 2:print(sizeof(CA), strideof(CA)) // 9, 12print(sizeof(CB), strideof(CB)) // 13, 16// Swift 3:print(MemoryLayout<CA>.size, MemoryLayout<CA>.stride) // 12, 12print(MemoryLayout<CB>.size, MemoryLayout<CB>.stride) // 16, 16
因为uint8_t d
是在尾巴填充后布局的struct CA sa
。
从Swift 3开始,对于 从C导入 的结构,两者size
和都stride
返回相同的值( 包括 结构填充) ,
即sizeof
返回与C中相同的值。
这是一个简单的函数,有助于演示以上内容(Swift 3):
func showMemory<T>(_ ptr: UnsafePointer<T>) { let data = Data(bytes: UnsafeRawPointer(ptr), count: MemoryLayout<T>.size) print(data as NSData)}
Swift中定义的结构:
var a = A(a: 0xaa, b: 0xbbbbbbbb, c: 0xcc)showMemory(&a) // <aa000000 bbbbbbbb cc>var b = B(sa: a, d: 0xdd)showMemory(&b) // <aa000000 bbbbbbbb ccdd>
从C导入的结构:
var ca = CA(a: 0xaa, b: 0xbbbbbbbb, c: 0xcc)showMemory(&ca) // <aa000000 bbbbbbbb cc000000>var cb = CB(ca: ca, d: 0xdd)showMemory(&cb) // <aa000000 bbbbbbbb cc000000 dd000000>
11.Swift 中的类和结构体
Swift中也有类和结构体,分别用struct和class声明,两则之间有很多相同之处,比如
- 1.定义属性用于存储值
- 2.定义方法用于提供功能
- 3.定义附属脚本用于访问值
- 4.定义构造器用于生成初始化值
- 5.通过扩展以增加默认实现的功能
- 6.实现协议以提供某种标准功能
但是类相比起结构体又多出一些特性,比如:
- 1.继承允许一个类继承另一个类的特征
- 2.类型转换允许在运行时检查和解释一个类实例的类型
- 3.析构器允许一个类实例释放任何其所被分配的资源
- 4.引用计数允许对一个类的多次引用
官方文档有推荐使用结构体的原则:
- 1.该数据结构的主要目的是用来封装少量相关简单数据值。
- 2.有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 3.该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用。
- 4.该数据结构不需要去继承另一个既有类型的属性或者行为。
举例来说,以下情境中适合使用结构体:
- 1.几何形状的大小,封装一个width属性和height属性,两者均为Double类型。
- 2.一定范围内的路径,封装一个start属性和length属性,两者均为Int类型。
- 3.三维坐标系内一点,封装x,y和z属性,三者均为Double类型。
这次就讲到这里,下次我们继续
5.6 类和结构两个类型的比较 [Swift原创教程]
原文:http://coolketang.com/staticCoding/5a9925ac17d0090035986868.html
1. 本节将类的引用特征和结构体进行比较,使你能够更清晰地明白类和结构体的区别。
2. 首先创建一个结构体。
3. 往结构体中添加两个属性。
4. 接着实例化结构体的对象,并设置它的两个属性的值。
5. 将该对象赋予一个变量,该变量也将具有和对象相同的属性,以及属性的值。
6. 这里修改新对象的属性的值。
7. 通过第13和第14行右侧的结果可以看出,结构体对象之间的值传递,采用的是拷贝的方式。两个对象都是相对独立的,一方发生变化,不会对另一方产生影响。
8. 接着我们再创建一个类。
9. 给类添加两个属性。
10. 接着添加一个初始化方法。
11. 在初始化方法中,给两个属性设置初始值。
12. 接着对类进行实例化,实例化的对象的两个属性,将拥有默认的值。
13. 然后将该对象赋予另一个对象。新对象拥有旧对象相同的类型、属性和方法,并且两者的两个属性的值也都是相同的。
14. 此时对第二个对象的属性的值进行修改。
15. 接着依次输出两个对象的属性,从右侧的实时反馈区可以看出,两个对象其实是对同一个实例的两个引用,当其中一个发生变化时,另一个也跟着发生变化。
16. 控制台输出的日志,也验证了类的引用特征,即类为引用类型,而结构体为值类型。
17. 最后使用全等号,来比较对同一个实例进行引用的两个对象。从右侧的结果可以看出,这两个对象是完全相同的。
C 11:unordered_map / set是否保证遍历顺序为插入顺序?
unordered_map<int,int> uii; uii.insert(make_pair(12,4)); uii.insert(make_pair(3,2)); uii.insert(make_pair(6,1)); uii.insert(make_pair(16,9)); ....
当我使用for循环访问此地图时,它按照我插入的正确顺序打印键.我测试了unordered_set,结果相同.
所以我的问题是,C标准是否保证访问顺序为插入顺序,就像Java的LinkedHashMap一样?
解决方法
Elements in an unordered associative container are organized into
buckets,keys with the same hash will end up in the same bucket. The
number of buckets is increased when the size of the container
increases to keep the average number of elements in each bucket under
a certain value.Rehashing invalidates iterator and might cause the elements to be
re-arranged in different buckets but it doesn’t invalidate references
to the elements.
这对unordered_map和unordered_set都有效.
您可能还想查看此问题Keep the order of unordered_map as we insert a new key
但是,在内部,无序容器的实现可能使用列表或其他有序容器来存储元素并仅存储对其子列表中的子列表的引用,这将使迭代顺序与插入顺序一致,直到插入足够的元素以导致列表重新排列.这是VS实现的情况.
Elasticsearch是否保持多值字段的顺序?
如何解决Elasticsearch是否保持多值字段的顺序??
当您从Elasticsearch取回文档时,所有数组的顺序都与索引该文档时的顺序相同。您返回的_source字段包含与索引相同的JSON文档。
但是,数组被索引(可搜索)为无序的多值字段。在搜索时,您不能引用“第一个元素”或“最后一个元素”。而是将数组视为一袋值。
因此,对于存储的字段,似乎保留了顺序,对于索引的字段,则没有保留。
解决方法
Elasticsearch是否保持多值字段的顺序?
即,如果我在字段中输入了以下值:
{
"values": ["one","two","three"],"values_original": ["1","2","3"]
}
(鉴于未分析字段)
我是否可以确定列表的内容将始终按照与放置列表相同的顺序返回?
在上面的示例中,我想确保“值”中第一个位置的“一个”将始终与“ values_original”等中的“ 1”相对应。
我也可以将其保留为嵌套对象,即
{
"values": [
{"original": "1","new": "one"},{"original":"2","new":"two"},{"original":"3","new":"three"}
]
}
但我想避免开销。
如果可以保证保留多值字段中的值顺序,那么我保留两个并行多值字段的方法将起作用。
今天的关于Swift是否保证类和结构中字段的存储顺序?和swift 存储属性的分享已经结束,谢谢您的关注,如果想了解更多关于11.Swift 中的类和结构体、5.6 类和结构两个类型的比较 [Swift原创教程]、C 11:unordered_map / set是否保证遍历顺序为插入顺序?、Elasticsearch是否保持多值字段的顺序?的相关知识,请在本站进行查询。
本文标签: