【问题标题】:How to create a pointer in Swift?如何在 Swift 中创建指针?
【发布时间】:2018-02-22 14:14:38
【问题描述】:

我正在使用 Swift 3。

我想要这个 C 语法:

int myVar;
int *pointer = &myVar;

所以修改 pointermyVar 做同样的事情。 另外我不知道这是否有任何区别,但在我的情况下,myVar 是一个包含类元素的数组,pointer 是指向该数组一个元素的指针。

【问题讨论】:

  • 你试过了吗? var selectedRow = rows[0] 以何种方式不做你想做的事? (根据您的描述,在我看来,您根本不需要副本,只需要一个共享指针。)
  • 它创建了rows[0] 的副本,但两个变量不同,当我修改selectedRow 时,它根本不会影响rows[0]。是的,我想要一个共享指针。

标签: swift pointers variables


【解决方案1】:

& 也存在于 Swift 中,但只能用作参数列表的一部分(例如 init、func、闭包)。

var i = 5
let ptr = UnsafeMutablePointer(&i)
print(ptr.pointee) // 5

// or
let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
ptr.initialize(to: 5)

// or with a closure
let ptr: UnsafePointer = { $0 }(&i)

【讨论】:

    【解决方案2】:

    (假设我明白你的要求......)

    在游乐场尝试以下代码。它应该打印 3 次“99”。

    class Row {
        var rowNumber = 0
    }
    
    var rows = [Row]()
    
    let testRow = Row()
    testRow.rowNumber = 1
    
    rows.append(testRow)
    
    let selectedRow = rows[0]
    selectedRow.rowNumber = 99
    
    print(testRow.rowNumber)
    print(selectedRow.rowNumber)
    print(rows[0].rowNumber)
    

    默认情况下,在赋值语句中不会复制对象。如果是结构体,那就不一样了。


    为了完整性添加一点:

    如果您想要使用标量值而不是对象来获得类似的效果,Swift 提供了各种类型的包装器。

    let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: 8)  // Should be 1, not 8 according to comment re: docs
    let other = intPointer
    other.pointee = 34
    
    print(intPointer.pointee)
    

    (警告:除了在操场上进行实验外,我没有将这些包装器用于任何事情。不要在没有做一些研究的情况下相信它。)

    【讨论】:

    • 好的,我在这里遗漏了一些东西。我认为我的代码不起作用,因为这种语法不正确,但是我在操场上尝试了您的代码并且它工作正常,所以我的代码也可以工作,我在其他地方一定有问题。现在为什么这适用于类而不适用于变量?例如var myVar = 5var otherVar = myVarotherVar = 5 不会改变myVar 的值?
    • 不同的是,对象是通过指针来引用的。因此,就我而言,我有一个实际对象和三个变量,其中包含一个指向它的值。在您的 myVar 示例中,您正在更改实际的变量内容;没有他们都引用的独立对象。 (这就像我输入 let selectedRow = Row() 并期望其更改会反映在 testRow 中一样。人们有时会尝试这样做,但它永远不会奏效。:)
    • 我很确定应该是.allocate(capacity: 1)。参数文档:要分配的内存量,以Pointee的实例计数。
    • 谢谢@nyg。这绝对不是我看过的真正用途的东西。
    【解决方案3】:

    与@Phillip 相同的示例。但我使用了结构。在这个例子中 rows[0] 不会改变:

    struct Row {
        var rowNumber = 0
    }
    
    var rows = [Row]()
    
    var testRow = Row()
    testRow.rowNumber = 1
    
    rows.append(testRow)
    
    var selectedRow = rows[0]
    selectedRow.rowNumber = 99
    
    print(testRow.rowNumber) // prints 1
    print(selectedRow.rowNumber) // prints 99
    print(rows[0].rowNumber)  // prints 1
    

    【讨论】:

      【解决方案4】:

      没有 C 风格的指针 (Unsafe Pointer),正如问题所问的那样,但是对象是通过引用共享的,结构是按值共享的:

      Swift assignpassreturn 引用 reference type 的值和值类型的副本

      structures 在代码中传递时总是被复制,但 classes 是通过引用传递的。

      例如

      如何拥有指向对象的指针/引用

      class Song {
          
          init(title: String, image: String, file: String, volume: Float, queuePlayer: AVQueuePlayer, playerLooper: AVPlayerLooper?) {
              self.title = title
              self.image = image
              ...
          }
          var title: String
          var image: String
          ...
      }
      
      var aSong = Song(title: "", image: "", ...)
      
      var arrOfSongReferences: [Song] = [Song]()
      arrOfSongReferences.append(aSong)
      
      var ptrToASong: Song = aSong
      
      aSong = nil
      // Due to Swift garbage collection ARC (Automatic Reference Counting), we still have references to the original aSong object so it won't be deleted
      

      如果数据是结构,你不能这样做

      struct Song {
          var title: String
          var image: String
          ...
      }
      
      var aSong: Song = Song(title: "", image: "", ...)
      var copyOfASong: Song = aSong
      

      方法

      你也可以通过引用传递给函数

      // this would be inside a class, perhaps Player. It doesn't have to be a static btw
      static func playSound(_ sound: inout Song, volume: Float = 0.0) {
              if (sound.playerLooper == nil) {
                     ...
              }
      }
      
      // usage
      Player.playSound(sound: &aSong)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-03
        • 1970-01-01
        • 2016-05-21
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多