代码之家  ›  专栏  ›  技术社区  ›  elmattic

address of和ref运算符之间的差异

  •  1
  • elmattic  · 技术社区  · 14 年前

    在我的代码中,我通过引用传递一些结构,声明它们是可变的,并使用 & 符号。问题是,在某些地方,字段已损坏(仅在发布模式下发生),我不知道绝对的原因。

    我找到了一个修复方法,使用ref关键字而不是operator的地址。我知道您可以自由地交换它们(在实例成员参数的情况下),但是为什么它解决了我的问题?

    [<Struct>]
    type MyStruct =
        val mutable private i : int
        val mutable private f : float
        new (a, b) = { i = a; f = b }
        member t.I = t.i
        member t.F = t.f
    
    type Printer () =
        member t.Print(data : MyStruct byref) = printfn "%d %f" data.I data.F
    
    let bar (p : Printer) =
        let mutable x = new MyStruct(2, 8.0)
        p.Print(&x)
    
    let foo (p : Printer) =
        let mutable y = new MyStruct(2, 8.0)
        p.Print(ref y) // What is exactly the difference, under the hood?
    
    let main () =
        foo (new Printer())
        bar (new Printer())
    do main ()
    

    使用byref传递结构似乎只对互操作场景有用,或者如果您想改变结构的字段。但这不是我的情况。我是否应该考虑按值传递结构类型(大约20字节左右)?

    1 回复  |  直到 14 年前
        1
  •  5
  •   Tomas Petricek    14 年前

    使用 ref

    let modify (data:int byref) = data <- 10
    
    let foo() = 
      let mutable n = 15 // Note: Compiles without 'mutable'
      modify (ref n)
      printfn "%d" n // Prints '10'!!
    

    你可能想要这样的东西:

    let foo() = 
      let n = ref 15
      modify n
      printfn "%d" (!n) // Prints '15'
    

    那么,有什么区别呢? 是一个获取值并创建堆分配的引用单元格的函数。在第二个示例中,类型 n ref<int> byref 参数-在这种情况下,它创建指向堆分配(引用单元格)对象的字段的指针。

    在第二个示例中,我们创建引用单元格,将指向引用单元格的指针传递给 modify 函数,然后使用 !<ref> 从引用单元格获取值的语法。在第一个例子中,我们在调用 函数(和 n个 从堆栈复制到堆分配的单元)。调用后不使用单元格(以及 n个 停留15)

    另一方面,一个 mutable 裁判 可变的 拜里夫 直接修改堆栈上的值。