c++ - parameter - Golang pasa las matrices a la función y la modifica
return arrays c++ (2)
Lo que está definiendo no es una array
sino una slice
de una matriz que se pasa por referencia como se especifica en la documentación de golang. Mira este enlace
En la mayoría de los lenguajes (como c ++) las matrices pasadas resultan en pasar implícitamente por una referencia, por lo que cualquier cambio en la matriz pasada en la función dará como resultado el cambio de la original. Estoy aprendiendo Golang, y en el libro "The Go Programming Language" de Alan AA Donovan y Brian W. Kernighan Se dice que su comportamiento es diferente al de otros idiomas: no pasa implícitamente array por referencia.
Me está confundiendo un poco, ¿no significa eso que pasar una matriz sin la referencia no debería modificar la matriz en sí? Déjame ilustrar eso:
func main() {
tab := []int{1, 2, 3}
fmt.Println(tab)
// Results in [1 2 3]
reverse(tab)
fmt.Println(tab)
// Results in [3 2 1]
}
func reverse(tab []int) {
for i, j := 0, len(tab)-1; i < j; i, j = i+1, j-1 {
tab[i], tab[j] = tab[j], tab[i]
}
}
En el código anterior, la matriz no pasa la matriz, pero la función inversa modifica la original, por lo que funciona de alguna manera como lo haría el programa C ++. ¿Alguien podría explicarme la diferencia?
PD: Lo siento si es una pregunta ficticia, soy totalmente nuevo en Golang y trato de entender bien los conceptos básicos.
La explicación es bastante simple: no hay una sola matriz declarada o utilizada explícitamente en su código anterior . La tab
la variable local y el parámetro de tab
son segmentos .
En Go, la longitud de una matriz es parte del tipo, por ejemplo [3]int
(esto es verdadero en una extensión que, por ejemplo, [2]int
y [3]int
son 2 tipos de matriz diferentes / distintos). Si la longitud no está presente (explícita como [2]int
o implícita como en el literal compuesto [...]int{1, 2, 3}
), entonces eso no es un tipo de matriz sino un tipo de división.
Sí, al leer, un valor de matriz significa todos sus elementos, y cuando se pasa (o se asigna), todos sus elementos se copian. Los sectores, sin embargo, son simplemente descriptores pequeños, encabezados, que describen una sección contigua de un conjunto; y cuando las divisiones se pasan (o se asignan), solo se copia este encabezado (el puntero incluido), que apuntará a la misma matriz subyacente. Por lo tanto, si modifica los elementos de la copia de división, los cambios se reflejarán en la división original ya que solo hay una matriz de respaldo que contiene los elementos.
Si desea saber exactamente qué hay en un encabezado de reflect.SliceHeader
, puede verificar el tipo reflect.SliceHeader
: es una struct
contiene el puntero al primer elemento del sector, la longitud y la capacidad del sector.
Lea las siguientes publicaciones de blog que explican esto en gran detalle:
Go Slices: uso y funcionamiento interno
Arrays, slices (y strings): la mecánica de ''append''
También vea estas preguntas relacionadas para más detalles: