我有一个很大的数组,我只想复制它的中间部分.我正试着用memcpy来做表演,但想不出办法.下面是一个例子.我们如何提供对震源的补偿?

var source: [UInt8] = [1,2,3,4,5,6,7,8,9]
var dest: [UInt8] = [0,0,0,0,0,0,0,0,0]

memcpy(&dest[2], source, 5)

print(dest) // [0, 0, 1, 2, 3, 4, 5, 0, 0]
// This works
var source: [UInt8] = [1,2,3,4,5,6,7,8,9]
var dest: [UInt8] = [0,0,0,0,0,0,0,0,0]

memcpy(&dest[2], &source[2], 5)

print(dest) // [0, 0, 3, 0, 0, 0, 0, 0, 0]
// Only `source[2]` is copied

推荐答案

为此,您可以使用replaceSubrange():

let source: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var dest: [UInt8] =   [0, 0, 0, 0, 0, 0, 0, 0, 0]

dest.replaceSubrange(2..<(2+5), with: source[2..<(2+5)])
print(dest) // [0, 0, 3, 4, 5, 6, 7, 0, 0]

或者只需将源片分配给目标片:

dest[2..<(2+5)] = source[2..<(2+5)]
print(dest) // [0, 0, 3, 4, 5, 6, 7, 0, 0]

基准

在MacBook Air M2上,代码在发布配置中编译.

import Foundation

let N = 1_000_000 // Length of source and destination array
let sourceStart = 500
let destinationStart = 2000
let length = 12345

let source: [UInt8] = Array(repeating: 5, count: N)

for _ in 1...10 {
    do {
        var dest: [UInt8] = Array(repeating: 0, count: N)
        let start = Date()
        
        dest[destinationStart..<(destinationStart+length)].withUnsafeMutableBufferPointer { p in
            source.copyBytes(to: p, from: sourceStart..<sourceStart + length)
        }
        let end = Date()
        print("copyBytes:      ", end.timeIntervalSince(start) * 1000, "ms")
    }
    do {
        var dest: [UInt8] = Array(repeating: 0, count: N)
        let start = Date()
        
        source.withUnsafeBytes { sourcePtr in
            _ = memcpy(&dest[destinationStart], sourcePtr.baseAddress! + sourceStart, length)
        }
        let end = Date()
        print("memcpy:         ", end.timeIntervalSince(start) * 1000, "ms")
    }
    do {
        var dest: [UInt8] = Array(repeating: 0, count: N)
        let start = Date()
        
        dest.replaceSubrange(destinationStart..<(destinationStart+length),
                             with: source[sourceStart..<(sourceStart+length)])
        
        let end = Date()
        print("replaceSubrange:", end.timeIntervalSince(start) * 1000, "ms")
    }
    do {
        var dest: [UInt8] = Array(repeating: 0, count: N)
        let start = Date()
        
        dest[destinationStart..<(destinationStart+length)]
            = source[sourceStart..<(sourceStart+length)]
        
        let end = Date()
        print("slicing:        ", end.timeIntervalSince(start) * 1000, "ms")
    }
    print()
}

结果:

copyBytes:       0.010013580322265625 ms
memcpy:          0.0010728836059570312 ms
replaceSubrange: 0.009059906005859375 ms
slicing:         0.010013580322265625 ms

Swift相关问答推荐

SwiftUI—如何识别单词并获取视觉中的位置

使用SWIFT宏从另一个枚举添加 case

如何使用Swift宏向 struct 体及其init函数添加新成员?

RealityKit(VisionOS)中的PhysicBodyComponent和DragGesture

SWIFT`String.Encoding`:`.unicode`vs`.utf16`

更改 SwiftUI 中按钮矩阵的填充 colored颜色

如何在visionOS中将模型锚定在用户头部上方?

如何使用 Swift 在非本地函数中切换()一个 Bool?

在 SwiftUI 中将属性显式设置为其默认值

如何为等待函数调用添加超时

如何在不提交到应用store 的情况下在本地运行我的应用

响应 UITextField (UIViewRepresentable) 中的特定按键

持久化字符串列表属性 RealmSwift

如何将回调传递给 View init

`IndexSet` 永远不会是空的?

在 Swift 4 中实现自定义解码器

将活动指示器 colored颜色 更改为黑色

如何在 Swift 中将 NSURL 转换为字符串

显示 UIAlertController 的简单 App Delegate 方法(在 Swift 中)

如何快速格式化用户显示(社交网络等)的时间间隔?