簡體   English   中英

指向二維數組中行的可變指針

[英]A mutable pointer to a row in a two-dimensional array

假設有一個二維數組

var myArray: [[MyClass]]

由於數組是Swift中的值類型,因此賦值就像

let line = myArray[lineNumber]

將創建一個副本,而不是引用實際的行。

為了修改數組上的行(例如在行中插入/刪除元素)而不復制元素並避免大量使用索引(即在代碼中多次使用myArray[lineNumber] ),我嘗試了使用C風格的指針方法。

分配

let rowPointer = UnsafePointer(myArray[rowNumber])

似乎沒有按預期方式工作,是指myArray[rowNumber][0]而不是整行。

然而,

let rowPointer = UnsafePointer(myArray) + rowNumber

可以rowPointer.pointee進行編譯並成功完成操作,因此rowPointer.pointee可以訪問整行

由於我還需要通過插入/追加元素來修改行,因此我嘗試了可變指針:

let rowPointer = UnsafeMutablePointer(myArray) + rowNumber

但是,此分配會產生編譯錯誤:

無法initializer for type 'UnsafeMutablePointer<_>' with an argument list of type '([[MyClass]])'調用initializer for type 'UnsafeMutablePointer<_>' with an argument list of type '([[MyClass]])'

有沒有一種方法可以通過可變指針訪問行?

您真正想做到的是添加對L值的支持。 可以分配或就地編輯的值。 在Swift中,這是通過下標運算符實現的:

struct Matrix<T> {
    var rows: [[T]]

    init(rows: [[T]]) { self.rows = rows }

    init(width: Int, height: Int, initialElement: T) {
        let rows = (0..<height).map { _ in
            return Array(repeating: initialElement, count: width)
        }
        self.init(rows: rows)
    }

    subscript(row: Int, col: Int) -> T {
        get { return self.rows[row][col] }
        set { self.rows[row][col] = newValue }
    }
}

extension Matrix: ExpressibleByArrayLiteral {
    init(arrayLiteral: [T]...) {
        self.init(rows: arrayLiteral)
    }
}

extension Matrix: CustomDebugStringConvertible {
    var debugDescription: String {
        let height = rows.first?.count ?? 0
        let rowText = rows.map { row in
            row.map { element in String(describing: element) }.joined(separator: ", ")
        }.joined(separator: "],\n\t[")

        return """
            Matrix(width: \(rows.count), height: \(height), rows:
                [\(rowText)]
            )
            """
    }
}

var matrix: Matrix = [
    ["A", "B"],
    ["C", "D"],
]

print(matrix)

matrix[0, 1] = "X"

print(matrix)

我強烈建議您使用不安全的指針方法,因為它可能導致您遇到各種懸空的指針或緩沖區溢出問題。 畢竟,“ Unsafe”名稱就在那里!

這是另一個顯示可變[[Any]]矩陣的簡單版本。

  let row1: NSMutableArray = [1,"22",3]
  let row2: NSMutableArray = [2,"33",3]
  let row3: NSMutableArray = [4,"4",5]

  let matrix: [NSMutableArray] = [row1, row2, row3] // Here matrix is an immutable. This is the difference from other answers.

  matrix[0][1] =  22
  matrix[0][2] =  "23"
  matrix[0][3] =  "2333"

  print(type(of:matrix[0][1])) //  __NSCFNumber
  print(type(of:matrix[0][2])) // NSTaggedPointerString

這更重要。

  let line1 = matrix[0] // here `let` again
  line1[2] = 33444

  print(matrix)  //matrix has changed. That means it is using reference. 

希望它有用。

這是修改數組實際指針的方法,但是我不確定它在現有數組副本上是否有任何實際價值。 由於值類型始終被復制,因此我們獲得了指針,更改了值並為指針分配了新值。

但是,最好將數組視為值類型,以通常的方式進行。 同樣,如果您的類是引用類型,則可以簡化很多事情。

var myArray: [[Int]] = [[1, 2, 3], [4, 5, 6]]

withUnsafeMutablePointer(to: &myArray) { pointer  in
    print(pointer)
    var pointee = pointer.pointee
    pointee[1][1] = 10
    pointer.pointee = pointee
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM