Comprensione byref, ref e &
-
14-11-2019 - |
Domanda
Bene, ho capito che F# è in grado di gestire i riferimenti (una sorta di C++ come riferimenti).Questo consente la possibilità di cambiare il valore dei parametri passati in funzioni e, inoltre, consente al programmatore di restituire più di un valore singolo.Tuttavia, ecco che cosa ho bisogno di sapere:
Parola chiave Ref:La parola chiave
ref
viene utilizzato per creare, da un valore, un riferimento a tale valore di tipo derivato.Cosìlet myref = ref 10
Questo significa che F# crea un oggetto di tipo
Ref<int>
mettere in una mutevole campo) il mioint 10
.OK.Quindi suppongo che
ref
viene utilizzato per creare istanze diRef<'a>
tipo.È corretto?Valore di accesso:Per accedere a un valore memorizzato in riferimento posso fare questo:
let myref = ref 10 let myval = myref.Value let myval2 = !myref
Mentre il
:=
operatore solo mi permette di modificare il valore come questo:let myref = ref 10 myref.Value <- 30 myref := 40
Così
!
(Bang) risolve il mio punto di riferimento.E:=
la modifica.Suppongo che questo sia corretta.L'operatore&:Che cosa significa questo operatore che fare?È per essere applicato a un tipo di riferimento?No, credo che deve essere applicata ad una mutevole valore e restituisce cosa?Il riferimento?L'indirizzo?Se si utilizza interattiva:
let mutable mutvar = 10;; &a;;
L'ultima riga genera un errore così non capisco che cosa l'
&
operatore per.ByRef:Che dire
byref
?Questo è molto importante per me, ma mi rendo conto di non capire.Capisco che è utilizzata in funzione per quanto riguarda il passaggio del parametro.Utilizza byref quando vuole che il valore passato può essere modificato (questo è un po 'contro i linguaggi funzionali' filosofia, ma f# è qualcosa di più).Si consideri il seguente:let myfunc (x: int byref) = x <- x + 10
Questo è strano.So che se si dispone di un riferimento
let myref = ref 10
e poi per modificare il valore:myref <- 10
essa si pone in un errore, in quanto dovrebbe essere come questo:myref := 10
.Tuttavia, il fatto che in quella funzione che è possibile modificarex
utilizzando il<-
operatore significa chex
non è un riferimento, giusto?Se si considera che
x
non è un riferimento, quindi presumo anche che, nelle funzioni, quando si utilizzabyref
su un parametro, il parametro può avere la mutevole sintassi applicata.Quindi è solo una questione di sintassi, se assumo io sono OK, e, infatti, tutto funziona (non errori del compilatore).Tuttavia, ciò che èx
?Funzioni di chiamata:Come posso utilizzare una funzione utilizzando parametri byref?
Il
&
l'operatore è stato coinvolto, ma potresti spiegare meglio per favore?In questo articolo: MSDN Parametri e Argomenti il seguente esempio:type Incrementor(z) = member this.Increment(i : int byref) = i <- i + z let incrementor = new Incrementor(1) let mutable x = 10 // A: Not recommended: Does not actually increment the variable. (Me: why?) incrementor.Increment(ref x) // Prints 10. printfn "%d" x let mutable y = 10 incrementor.Increment(&y) (* Me: & what does it return? *) // Prints 11. printfn "%d" y let refInt = ref 10 incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *) // Prints 11. printfn "%d" !refInt
Soluzione
Parola chiave Ref Sì, quando si scrive let a = ref 10
essenzialmente si scrittura let a = new Ref<int>(10)
dove il Ref<T>
il tipo ha una mutevole campo Value
.
Valore di accesso Il :=
e !
gli operatori sono solo scorciatoie per la scrittura:
a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
ByRef è un tipo speciale che può essere (ragionevolmente), utilizzata solo nei parametri del metodo.Significa che l'argomento deve essere essenzialmente un puntatore a qualche posizione di memoria (allocato su heap stack).Corrisponde a out
e ref
modificatori in C#.Si noti che non è possibile creare una variabile locale di questo tipo.
L'operatore & è un modo per creare un valore (un puntatore) che può essere passato come argomento di una funzione/metodo attesa di un byref
tipo.
Funzioni di chiamata l'esempio con byref
funziona perché si stanno passando il metodo di un riferimento a un locale mutevole variabile.Via di riferimento, il metodo può modificare il valore memorizzato nella variabile.
Il seguente non funziona:
let a = 10 // Note: You don't even need 'mutable' here
bar.Increment(ref a)
Il motivo è che si sta creando una nuova istanza di Ref<int>
e si copia il valore di a
in questa istanza.Il Increment
metodo, quindi, modifica il valore memorizzato sul heap nell'istanza di Ref<int>
, ma non è un riferimento a questo oggetto più.
let a = ref 10
bar.Increment(a)
Questo funziona, perché a
è un valore di tipo Ref<int>
e stai passando un puntatore all'allocazione heap istanza di Increment
e quindi ottenere il valore allocazione heap di riferimento di cella utilizzando !a
.
(È possibile utilizzare i valori creati utilizzando ref
come argomenti per byref
perché il compilatore gestisce questo caso speciale, questo verrà automaticamente di riferimento del Value
campo, perché questo è uno scenario utile...).