Swift 缓冲区指针和数组索引

Swift buffer pointer & array indexing

我有以下代码:

 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 是如何工作的呢?上面的代码如果错了怎么改(虽然能用,但不一定对)?

您的代码是正确的。

someArray.withUnsafeMutableBufferPointer { bufPtr in ... }

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

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

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

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