首页 > 解决方案 > Swift 缓冲区指针和数组索引

问题描述

我有以下代码:

 public struct HistogramData {
   var red:[vImagePixelCount] = []
   var green:[vImagePixelCount] = []
   var blue: [vImagePixelCount] = []
   var alpha: [vImagePixelCount] = []
 }

然后我按如下方式访问它:

     var data: HistogramData
     ...

     let red:UnsafeMutablePointer<vImagePixelCount> =  UnsafeMutablePointer(mutating: data.red)
      let green:UnsafeMutablePointer<vImagePixelCount> = UnsafeMutablePointer(mutating: data.green)
      let blue:UnsafeMutablePointer<vImagePixelCount> = UnsafeMutablePointer(mutating: data.blue)

上述行不正确,XCode 显示悬空指针的警告。所以我将代码修改为:

  data.red.withUnsafeMutableBufferPointer { redPtr in
            data.green.withUnsafeMutableBufferPointer { greenPtr in
                data.blue.withUnsafeMutableBufferPointer { bluePtr in
                    
                    let red = redPtr.baseAddress!
                    let green = greenPtr.baseAddress!
                    let blue = bluePtr.baseAddress!
                    
                    for i in 0..<256 {
                        if red[i] > maxR {
                            maxR = red[i]
                        }
                        
                        if green[i] > maxG {
                            maxG = green[i]
                        }
                        
                        if blue[i] > maxB {
                            maxB = blue[i]
                        }
                    }

               ...
         }

即使上面的代码有效,但我不确定我们是否可以在 Swift 中的 baseAddress 上使用数组索引。正确的方法可能是将内存绑定到一定的大小,但是当数组的大小没有指定时,bindMemory 是如何工作的呢?如果上面的代码是错误的,我该如何修复(即使它可能有效,但它可能不正确)?

标签: iosswiftunsafemutablepointer

解决方案


你的代码是正确的。

someArray.withUnsafeMutableBufferPointer { bufPtr in ... }

使用引用数组的(可变)元素存储来调用闭包,UnsafeMutableBufferPointer并且已经绑定到元素的类型。仅当您想以不同类型访问内存时才需要重新绑定。

然后两者都bufPtr[i]访问bufPtr.baseAddress![i]第 i 个数组元素(通过resp.的subscript方法)。唯一的区别是前者在调试模式下对索引进行边界检查。UnsafeMutableBufferPointerUnsafeMutablePointer

在优化的代码中,两种下标方法都可以访问元素存储而无需进行边界检查。这可能是一种提高性能的方法(以安全为代价)。

如果你的这部分代码对性能至关重要,并且不安全的访问真的比“正常”的数组访问快,我建议进行基准测试。


推荐阅读