在Objective-c
的世界中,一切对象都是指针。它是一种运行时语言,具体指针的对象类型将会在运行时,由系统分配。这样虽然自由,可是却并不安全。编程
Swift
世界就不同了,Swift
的世界很安全(至少大部分时候状况如此)。咱们没必要为对象运行时的类型担心,这是Swift
为咱们构筑的一层堡垒。可是在一些时候,这层堡垒也成为束缚咱们行为的操做。swift
Swift
也为操做指针这种不安全行为提供了支持。数组
MemoryLayout
MemoryLayout
是Swift 为结构体struct
等一些须要获取具体内存空间大小定义的枚举。安全
它包含一系列方法,可使咱们更方便的使用。bash
主要属性就是三个:socket
/// 对应类型的实例在内存占用的真实字节大小
public static var size: Int { get }
/// 对应类型的实例在内存通过对齐后占用的字节大小 (内存对齐请参照百度百科,连接将会在下文给出)
public static var stride: Int { get }
/// 默认内存对齐单位
public static var alignment: Int { get }
复制代码
内存对齐百度百科: baike.baidu.com/item/内存对齐/9…编程语言
这三个属性也是咱们常用的,对应还有三个从实例对象中获取的方法ide
playgroud 介绍代码函数
struct Test {
let res1: Bool = false
let res2: Int = 0
let res3: Bool = false
}
print("\(MemoryLayout<Test>.stride)") // 24
复制代码
由于这个类不是咱们首要要介绍的,因此就只是大概介绍学习
指针定义:
在计算机科学中,**指针(Pointer)**是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另外一个地方的值。因为经过地址能找到所需的变量单元,能够说,地址指向该变量单元。所以,将地址形象化的称为“指针”。意思是经过它能找到以它为地址的内存单元。
节选自百度百科: baike.baidu.com/item/指针/287…
Swift
中认为全部的指针相关操做都是不安全的,因此全部指针相关的结构体都会包含有前缀Unsafe
Swift
中一共有8个结构体
Swift | Objective-c | 描述 |
---|---|---|
UnsafePointer<T> |
const T * |
指针及其所指向的内存内容均不可变 |
UnsafeMutablePointer<T> |
T * |
指针及其所指向的内存内容都可变 |
UnsafeBufferPointer<T> |
const T * [] |
是一个指针数组内容均不可变 |
UnsafeMutableBufferPointer<T> |
T * [] |
|
UnsafeRawPointer |
const void * |
|
UnsafeMutableRawPointer |
void * |
|
UnsafeBufferRawPointer |
void * [] |
首先要说一个实例类对象如何转化为指针
UnsafePointer
代码展现:
struct Obj {
var name: Int = 5
}
var obj = Obj()
let pointer = withUnsafePointer(to: &obj, {$0})
print("\(pointer.pointee)")
复制代码
这里注意了,UnsafePointer.pointee
只有get
方法,也就是至关于咱们获取了一个let
的对象,听从于let
的相关要求。
注:这里多介绍一下let
和var
的区别
let
和var
都是swift
声明变量时候的前缀。在程序中,当咱们声明变量的时候,在真实运行时候的环境里,程序便会为咱们声明的变量初始化对应的内存。
let
声明的变量的内存内容,在声明初始化事后便再也不可变
var
声明的变量的内存内容,在随后能够随时被修改。这里咱们使用的是内存内容,也就是抽象的内存地址里的那些0、1的值。
对于
class
,let
和var
的区别是这个变量能不能再被赋值一个新的类对象,而对原有对象的相关存储属性的修改,并不受影响。这是由于class
的对象在声明时候的堆栈内存内容,只有8个字节(咱们可使用MemoryLayout
获取),真实对象的存储在其余位置。因此咱们能修改let
指向的值对于
struct
,let
和var
的区别就是let
建立的对象,不论属性是用let
仍是var
,咱们都没法直接修改值。只能修改var
修饰的。这个是由于struct
对象是直接存储在声明时候的内存内容里。
对于UnsafeMutablePointer来讲,pointee即是set
和get
方法了,也就是说,咱们能够直接修改对应内存地址的值了。
这里展现下如何获取UnsafeMutablePointer与修改相关值
struct Obj {
var name: Int = 5
init(name: Int = 5) {
self.name = name
}
}
var obj = Obj()
let pointer = withUnsafeMutablePointer(to: &obj, {$0})
print("Obj: \(obj)")
pointer.pointee = Obj(name: 10)
print("\(pointer.pointee)")
print("Obj: \(obj)")
复制代码
当运行这段代码的时候,咱们能够看到,obj
的内容也随着指针变化了。
注:obj
只能使用var
声明,由于Unsafe
类的调用须要使用&
,同时有可能产生内存内容的变化,所以let
定义下不符合相关要求。
接下来是我要讲的就是Swift中等同于C语言中void *
的指针UnsafeRawPointer
在苹果的官方文档中,关于UnsafeRawPointer
的定义为
A raw pointer for accessing untyped data.
一个用来访问未定义类型的指针
Overview
The UnsafeRawPointer type provides no automated memory management, no type safety, and no alignment guarantees. You are responsible for handling the life cycle of any memory you work with through unsafe pointers, to avoid leaks or undefined behavior.
UnsafeRawPointer 提供了没有自动内存管理,没有类型安全,与内存对齐控制保证。你有义务去本身管理你经过指针引用的任何内存的声明周期,以免内存泄漏或者其他未定义(不安全)的行为
Memory that you manually manage can be either untyped or bound to a specific type. You use the UnsafeRawPointer type to access and manage raw bytes in memory, whether or not that memory has been bound to a specific type.
你手动管理的内存能够是未定义内存的,或者是被定义到一个指定的类型的。你可使用UnsafeRawPointer去访问和管理未被定义的内存字节,而无需在乎这段内存是否已经被绑定到一个指定的类型。
官方定义是这样的,大体思路就是,若是你有需求须要本身管理内存的时候,使用这个类。通常就是咱们操做底层的一些代码,这个会须要被当成参数传入。
代码示例:
var i = 2
let pointerRaw = withUnsafeBytes(of: &i, {$0})
guard let pointer = pointerRaw.bindMemory(to: Int.self).baseAddress else { fatalError("这段代码理论上不能执行到这") }
let j = pointer.pointee
print("j:\(j)")
复制代码
以上代码就是转换rawPointer和pointer的例子了。剩下的是bufferPointer,由于使用的地方较少了,故此不深刻介绍了。
指针相关中最重要的几个操做就是指针的生成,与将指针转化成实例对象。其中重要的就是pointee
和几个withUnsafeXX
的全局函数。
在swift
中,指针的世界并不复杂,全部指针的操做都能转化为8个UnsafeXX
类。咱们的使用也是基于此的,咱们若是使用某些底层方法须要指针,这个时候只须要将相应的指针对象生成便可传入。
一转眼已经元旦了,期间也想过写一些文章,可是对于没什么东西要写感到困惑。同时,这段时间也是一直在学习Swift
的相关语言。由于我的项目中将要用到socket操做,因而决定用Swift
重写GCDAsyncSocket
。在重写过程当中遇到了不少指针相似的问题,因而决定写一篇关于指针的教程。
Swift的socket库SwiftAsyncSocket
目前正在完善中,TCP/IP协议基础功能已基本完善。近期将会正式开源
本文首发于,本人博客与公众号(见下图),若是但愿转载到公众号,请联系本人开通权限。
最后,祝你们新年快乐,心想事成