Article / 2026/05/29

BufferPointer

BufferPointer 是 Swift 中用于安全访问内存缓冲区的类型。它提供了一种类型安全的方式来处理连续内存块,常用于与 C API 交互、性能优化和底层内存操作。

BufferPointer

概述

BufferPointer 是 Swift 中用于安全访问内存缓冲区的类型。它提供了一种类型安全的方式来处理连续内存块,常用于与 C API 交互、性能优化和底层内存操作。

Swift 提供了两种主要的 BufferPointer 类型:

  • UnsafeBufferPointer<Element>: 只读缓冲区指针
  • UnsafeMutableBufferPointer<Element>: 可读写缓冲区指针

UnsafeBufferPointer

基本概念

UnsafeBufferPointer 是一个只读的缓冲区指针,提供对连续内存区域的安全访问。

初始化方法

// 示例代码
import Foundation

// 1. 从数组创建
let array = [1, 2, 3, 4, 5]
array.withUnsafeBufferPointer { buffer in
    print("Buffer count: \(buffer.count)")
    print("First element: \(buffer[0])")
}

// 2. 从原始指针创建
let rawPointer = UnsafePointer<Int>.allocate(capacity: 3)
rawPointer.initialize(to: 10)
(rawPointer + 1).initialize(to: 20)
(rawPointer + 2).initialize(to: 30)

let buffer = UnsafeBufferPointer(start: rawPointer, count: 3)
print("Buffer from raw pointer: \(Array(buffer))")

rawPointer.deallocate()

// 3. 空缓冲区
let emptyBuffer = UnsafeBufferPointer<Int>(start: nil, count: 0)
print("Empty buffer count: \(emptyBuffer.count)")

输出结果:

Buffer count: 5
First element: 1
Buffer from raw pointer: [10, 20, 30]
Empty buffer count: 0

主要属性

let data = [10, 20, 30, 40, 50]
data.withUnsafeBufferPointer { buffer in
    // 基本属性
    print("Count: \(buffer.count)")           // 元素数量
    print("Is empty: \(buffer.isEmpty)")      // 是否为空
    print("Base address: \(buffer.baseAddress)") // 基地址
    
    // 索引相关
    print("Start index: \(buffer.startIndex)")   // 起始索引
    print("End index: \(buffer.endIndex)")       // 结束索引
    
    // 内存相关
    print("Memory size: \(MemoryLayout<Int>.size * buffer.count) bytes")
}

输出结果:

Count: 5
Is empty: false
Base address: Optional(0x...)
Start index: 0
End index: 5
Memory size: 40 bytes

访问方法

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

numbers.withUnsafeBufferPointer { buffer in
    // 1. 下标访问
    print("Element at index 2: \(buffer[2])")
    
    // 2. 安全访问
    if let first = buffer.first {
        print("First element: \(first)")
    }
    
    if let last = buffer.last {
        print("Last element: \(last)")
    }
    
    // 3. 切片操作
    let slice = buffer[2..<5]
    print("Slice [2..<5]: \(Array(slice))")
    
    // 4. 前缀和后缀
    let prefix = buffer.prefix(3)
    print("Prefix 3: \(Array(prefix))")
    
    let suffix = buffer.suffix(3)
    print("Suffix 3: \(Array(suffix))")
    
    // 5. 删除前缀和后缀
    let dropFirst = buffer.dropFirst(2)
    print("Drop first 2: \(Array(dropFirst))")
    
    let dropLast = buffer.dropLast(2)
    print("Drop last 2: \(Array(dropLast))")
}

输出结果:

Element at index 2: 3
First element: 1
Last element: 10
Slice [2..<5]: [3, 4, 5]
Prefix 3: [1, 2, 3]
Suffix 3: [8, 9, 10]
Drop first 2: [3, 4, 5, 6, 7, 8, 9, 10]
Drop last 2: [1, 2, 3, 4, 5, 6, 7, 8]

遍历和查找

let values = [5, 2, 8, 1, 9, 3, 7, 4, 6]

values.withUnsafeBufferPointer { buffer in
    // 1. 遍历
    print("All elements:")
    for (index, value) in buffer.enumerated() {
        print("  [\(index)]: \(value)")
    }
    
    // 2. 查找
    if let foundIndex = buffer.firstIndex(of: 8) {
        print("Found 8 at index: \(foundIndex)")
    }
    
    if let foundIndex = buffer.firstIndex(where: { $0 > 7 }) {
        print("First element > 7 at index: \(foundIndex), value: \(buffer[foundIndex])")
    }
    
    // 3. 包含检查
    print("Contains 5: \(buffer.contains(5))")
    print("Contains element > 10: \(buffer.contains { $0 > 10 })")
    
    // 4. 计数
    let evenCount = buffer.count { $0 % 2 == 0 }
    print("Even numbers count: \(evenCount)")
}

输出结果:

All elements:
  [0]: 5
  [1]: 2
  [2]: 8
  [3]: 1
  [4]: 9
  [5]: 3
  [6]: 7
  [7]: 4
  [8]: 6
Found 8 at index: 2
First element > 7 at index: 2, value: 8
Contains 5: true
Contains element > 10: false
Even numbers count: 4

函数式操作

let source = [1, 2, 3, 4, 5]

source.withUnsafeBufferPointer { buffer in
    // 1. Map 操作
    let doubled = buffer.map { $0 * 2 }
    print("Doubled: \(doubled)")
    
    // 2. Filter 操作
    let evens = buffer.filter { $0 % 2 == 0 }
    print("Even numbers: \(evens)")
    
    // 3. Reduce 操作
    let sum = buffer.reduce(0, +)
    print("Sum: \(sum)")
    
    let product = buffer.reduce(1, *)
    print("Product: \(product)")
    
    // 4. CompactMap 操作
    let halfIfEven = buffer.compactMap { $0 % 2 == 0 ? $0 / 2 : nil }
    print("Half of even numbers: \(halfIfEven)")
    
    // 5. 条件检查
    let allPositive = buffer.allSatisfy { $0 > 0 }
    print("All positive: \(allPositive)")
    
    let hasLarge = buffer.contains { $0 > 3 }
    print("Has number > 3: \(hasLarge)")
}

输出结果:

Doubled: [2, 4, 6, 8, 10]
Even numbers: [2, 4]
Sum: 15
Product: 120
Half of even numbers: [1, 2]
All positive: true
Has number > 3: true

UnsafeMutableBufferPointer

基本概念

UnsafeMutableBufferPointer 提供对可变缓冲区的访问,允许修改缓冲区内容。

初始化和基本操作

// 1. 分配内存创建可变缓冲区
let capacity = 5
let rawPointer = UnsafeMutablePointer<Int>.allocate(capacity: capacity)
let mutableBuffer = UnsafeMutableBufferPointer(start: rawPointer, count: capacity)

// 2. 初始化缓冲区
for i in 0..<capacity {
    mutableBuffer[i] = i * 10
}

print("Initial buffer: \(Array(mutableBuffer))")

// 3. 修改元素
mutableBuffer[2] = 999
print("After modification: \(Array(mutableBuffer))")

// 4. 批量操作
mutableBuffer.update(repeating: 42)
print("After update repeating: \(Array(mutableBuffer))")

// 清理内存
rawPointer.deallocate()

输出结果:

Initial buffer: [0, 10, 20, 30, 40]
After modification: [0, 10, 999, 30, 40]
After update repeating: [42, 42, 42, 42, 42]

从数组创建可变缓冲区

var array = [1, 2, 3, 4, 5]

array.withUnsafeMutableBufferPointer { buffer in
    print("Original: \(Array(buffer))")
    
    // 修改单个元素
    buffer[0] = 100
    buffer[4] = 500
    
    print("After single modifications: \(Array(buffer))")
    
    // 交换元素
    buffer.swapAt(1, 3)
    print("After swap at 1,3: \(Array(buffer))")
    
    // 排序
    buffer.sort()
    print("After sorting: \(Array(buffer))")
}

print("Final array: \(array)")

输出结果:

Original: [1, 2, 3, 4, 5]
After single modifications: [100, 2, 3, 4, 500]
After swap at 1,3: [100, 4, 3, 2, 500]
After sorting: [2, 3, 4, 100, 500]
Final array: [2, 3, 4, 100, 500]

高级修改操作

var data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

data.withUnsafeMutableBufferPointer { buffer in
    print("Original: \(Array(buffer))")
    
    // 1. 部分排序
    buffer[2..<6].sort()
    print("After partial sort [2..<6]: \(Array(buffer))")
    
    // 2. 反转子范围
    buffer[1..<4].reverse()
    print("After reverse [1..<4]: \(Array(buffer))")
    
    // 3. 填充子范围
    buffer[6..<9].update(repeating: -1)
    print("After fill [6..<9] with -1: \(Array(buffer))")
    
    // 4. 随机打乱
    buffer.shuffle()
    print("After shuffle: \(Array(buffer))")
}

输出结果:

Original: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
After partial sort [2..<6]: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
After reverse [1..<4]: [10, 30, 20, 40, 50, 60, 70, 80, 90, 100]
After fill [6..<9] with -1: [10, 30, 20, 40, 50, 60, -1, -1, -1, 100]
After shuffle: [随机顺序的数组]

内存操作

// 演示不同类型的内存操作
func demonstrateMemoryOperations() {
    let sourceArray = [1, 2, 3, 4, 5]
    var targetArray = Array(repeating: 0, count: 5)
    
    // 1. 使用 initialize 方法
    let pointer1 = UnsafeMutablePointer<Int>.allocate(capacity: 5)
    let buffer1 = UnsafeMutableBufferPointer(start: pointer1, count: 5)
    
    buffer1.initialize(repeating: 99)
    print("Initialized with 99: \(Array(buffer1))")
    
    // 2. 从集合初始化
    let pointer2 = UnsafeMutablePointer<Int>.allocate(capacity: 5)
    let buffer2 = UnsafeMutableBufferPointer(start: pointer2, count: 5)
    
    _ = buffer2.initialize(from: sourceArray)
    print("Initialized from array: \(Array(buffer2))")
    
    // 3. 复制到另一个缓冲区
    targetArray.withUnsafeMutableBufferPointer { targetBuffer in
        targetBuffer.update(from: buffer2)
        print("Copied to target: \(Array(targetBuffer))")
    }
    
    // 清理内存
    pointer1.deallocate()
    pointer2.deallocate()
    
    print("Final target array: \(targetArray)")
}

demonstrateMemoryOperations()

输出结果:

Initialized with 99: [99, 99, 99, 99, 99]
Initialized from array: [1, 2, 3, 4, 5]
Copied to target: [1, 2, 3, 4, 5]
Final target array: [1, 2, 3, 4, 5]

实际应用场景

1. 与 C API 交互

import Foundation

// 模拟 C 函数
func processIntArray(_ ptr: UnsafePointer<Int32>?, _ count: Int32) -> Int32 {
    guard let ptr = ptr else { return 0 }
    var sum: Int32 = 0
    for i in 0..<Int(count) {
        sum += ptr[i]
    }
    return sum
}

// Swift 端使用
let swiftArray: [Int32] = [10, 20, 30, 40, 50]
let result = swiftArray.withUnsafeBufferPointer { buffer in
    return processIntArray(buffer.baseAddress, Int32(buffer.count))
}

print("C function result: \(result)")

输出结果:

C function result: 150

2. 高性能数据处理

// 高性能的数组操作示例
func performanceComparison() {
    let size = 1_000_000
    let largeArray = Array(1...size)
    
    // 使用 BufferPointer 的高性能版本
    let startTime = CFAbsoluteTimeGetCurrent()
    
    let sum = largeArray.withUnsafeBufferPointer { buffer in
        var total = 0
        for i in 0..<buffer.count {
            total += buffer[i]
        }
        return total
    }
    
    let endTime = CFAbsoluteTimeGetCurrent()
    let duration = endTime - startTime
    
    print("Sum: \(sum)")
    print("Processing time: \(duration) seconds")
    print("Elements per second: \(Double(size) / duration)")
}

performanceComparison()

3. 自定义集合类型

// 使用 BufferPointer 实现自定义集合
struct FixedSizeBuffer<T> {
    private let pointer: UnsafeMutablePointer<T>
    private let capacity: Int
    private var count: Int = 0
    
    init(capacity: Int) {
        self.capacity = capacity
        self.pointer = UnsafeMutablePointer<T>.allocate(capacity: capacity)
    }
    
    deinit {
        pointer.deallocate()
    }
    
    mutating func append(_ element: T) {
        guard count < capacity else {
            fatalError("Buffer overflow")
        }
        pointer[count] = element
        count += 1
    }
    
    func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<T>) throws -> R) rethrows -> R {
        let buffer = UnsafeBufferPointer(start: pointer, count: count)
        return try body(buffer)
    }
    
    mutating func withUnsafeMutableBufferPointer<R>(_ body: (UnsafeMutableBufferPointer<T>) throws -> R) rethrows -> R {
        let buffer = UnsafeMutableBufferPointer(start: pointer, count: count)
        return try body(buffer)
    }
}

// 使用示例
var buffer = FixedSizeBuffer<Int>(capacity: 5)
buffer.append(10)
buffer.append(20)
buffer.append(30)

buffer.withUnsafeBufferPointer { ptr in
    print("Buffer contents: \(Array(ptr))")
}

buffer.withUnsafeMutableBufferPointer { ptr in
    ptr[1] = 999
    print("After modification: \(Array(ptr))")
}

输出结果:

Buffer contents: [10, 20, 30]
After modification: [10, 999, 30]

安全注意事项

1. 内存安全

// ❌ 错误示例 - 悬空指针
func dangerousExample() {
    var array = [1, 2, 3]
    var unsafeBuffer: UnsafeBufferPointer<Int>!
    
    array.withUnsafeBufferPointer { buffer in
        unsafeBuffer = buffer  // 危险!缓冲区会在闭包结束后失效
    }
    
    // 此时使用 unsafeBuffer 是不安全的
    // print(unsafeBuffer[0])  // 可能崩溃
}

// ✅ 正确示例 - 在闭包内完成所有操作
func safeExample() {
    let array = [1, 2, 3]
    let result = array.withUnsafeBufferPointer { buffer in
        return buffer.reduce(0, +)
    }
    print("Safe result: \(result)")
}

safeExample()

2. 边界检查

func boundaryCheckExample() {
    let array = [1, 2, 3]
    
    array.withUnsafeBufferPointer { buffer in
        // ✅ 安全访问
        if buffer.indices.contains(1) {
            print("Safe access: \(buffer[1])")
        }
        
        // ✅ 使用安全的访问方法
        if let element = buffer.first {
            print("First element: \(element)")
        }
        
        // ❌ 危险 - 可能越界
        // print(buffer[10])  // 可能崩溃
        
        // ✅ 边界检查
        let index = 10
        if index < buffer.count {
            print("Element at \(index): \(buffer[index])")
        } else {
            print("Index \(index) is out of bounds")
        }
    }
}

boundaryCheckExample()

输出结果:

Safe result: 6
Safe access: 2
First element: 1
Index 10 is out of bounds

最佳实践

  1. 始终在闭包内完成 BufferPointer 操作,不要让指针逃逸到闭包外部
  2. 进行边界检查,避免数组越界访问
  3. 及时释放手动分配的内存,避免内存泄漏
  4. 使用类型安全的 API,优先使用 Swift 标准库提供的高级抽象
  5. 性能敏感场景下使用,在常规情况下使用 Array 等高级类型

总结

BufferPointer 是 Swift 中处理底层内存操作的重要工具,它提供了类型安全的方式来访问连续内存块。虽然功能强大,但需要小心使用以避免内存安全问题。在大多数情况下,Swift 的高级集合类型已经足够使用,BufferPointer 主要用于性能关键场景和与 C API 的交互。

Giscus 未启用:请在 src/site.config.ts 中配置 repoId 与 categoryId。