Maison  >  Article  >  développement back-end  >  Aller à la comparaison des langages en passant le paramètre de référence C++

Aller à la comparaison des langages en passant le paramètre de référence C++

巴扎黑
巴扎黑original
2017-09-02 11:16:131436parcourir

Cet article explique principalement si Go a un passage de paramètres par référence (par rapport au C++). Les amis qui en ont besoin peuvent se référer à

Trois méthodes de passage de paramètres en C++

Passage de valeurs :

La méthode la plus courante de transmission de paramètres. Les paramètres formels d'une fonction sont des copies des paramètres réels. n'affectera pas les paramètres formels en dehors de la fonction. Généralement, le passage de valeur est utilisé lors de la modification de paramètres dans une fonction sans affecter l'appelant.

Passage de pointeur

Le paramètre formel est un pointeur vers l'adresse du paramètre réel, comme son nom l'indique, lorsque le contenu pointé par le paramètre formel est manipulé. dans la fonction, le paramètre lui-même sera modifié.

Passage par référence

En C++, une référence est un alias pour une variable, qui est en fait la même chose et existe également à la même adresse en mémoire. En d’autres termes, partout où une référence est manipulée, la variable référencée est directement manipulée.

Regardez la démo ci-dessous :


#include <iostream>
//值传递
void func1(int a) {
  std::cout << "值传递,变量地址:" << &a << ", 变量值:" << a << std::endl;
  a ++ ;
}
//指针传递
void func2 (int* a) {
  std::cout << "指针传递,变量地址:" << a << ", 变量值:" << *a << std::endl;
  *a = *a + 1;
}
//引用传递
void func3 (int& a) {
  std::cout << "指针传递,变量地址:" << &a << ", 变量值:" << a << std::endl;
  a ++;
}
int main() {
  int a = 5;
  std::cout << "变量实际地址:" << &a << ", 变量值:" << a << std::endl;
  func1(a);
  std::cout << "值传递操作后,变量值:" << a << std::endl;
  std::cout << "变量实际地址:" << &a << ", 变量值:" << a << std::endl;
  func2(&a);
  std::cout << "指针传递操作后,变量值:" << a << std::endl;
  std::cout << "变量实际地址:" << &a << ", 变量值:" << a << std::endl;
  func3(a);
  std::cout << "引用传递操作后,变量值:" << a << std::endl;
  return 0;
}
Le résultat de sortie est le suivant :

Adresse réelle de la variable : 0x28feac, variable valeur : 5

Transfert de valeur, adresse variable : 0x28fe90, valeur variable : 5
Après l'opération de transfert de valeur, valeur variable : 5
Adresse réelle de la variable : 0x28feac, valeur variable : 5
Transfert de pointeur, variable adresse : 0x28feac, valeur variable : 5
Après l'opération de transfert de pointeur, valeur variable : 6
Adresse réelle de la variable : 0x28feac, valeur variable : 6
Transfert de pointeur, adresse variable : 0x28feac, valeur variable : 6
Après l'opération de transfert de référence, Valeur de la variable : 7

Passage des paramètres dans Go

Ce qui précède présente les trois méthodes de passage des paramètres de C++, le passage de valeurs et le passage de pointeurs sont faciles à comprendre, alors Go dispose-t-il également de ces méthodes de passage de paramètres ? Cela a suscité une controverse, mais par rapport au concept de passage de références en C++, on peut dire que Go n'a pas de méthode de passage de références. Pourquoi je dis cela ? Parce que Go n'a pas le concept de références variables. Mais Go a des types de référence, qui seront expliqués plus tard.

Regardons d'abord un exemple de transmission de valeurs et de pointeurs dans Go :


package main
import (
  "fmt"
)
func main() {
  a := 1
  fmt.Println( "变量实际地址:", &a, "变量值:", a)
  func1 (a)
  fmt.Println( "值传递操作后,变量值:", a)
  fmt.Println( "变量实际地址:", &a, "变量值:", a)
  func2(&a)
  fmt.Println( "指针传递操作后,变量值:", a)
}
//值传递
func func1 (a int) {
  a++
  fmt.Println( "值传递,变量地址:", &a, "变量值:", a)
}
//指针传递
func func2 (a *int) {
  *a = *a + 1
  fmt.Println( "指针传递,变量地址:", a, "变量值:", *a)
}
Le résultat de sortie est le suivant :

L'adresse réelle de la variable : 0xc04203c1d0 Valeur de la variable : 1

Transfert de valeur, adresse de la variable : 0xc04203c210 Valeur de la variable : 2
Après l'opération de transfert de valeur, valeur de la variable : 1
Adresse réelle de la variable : 0xc04203c1d0 Variable valeur : 1
Transfert de pointeur, adresse variable : 0xc04203c1d0 Valeur de la variable : 2
Après l'opération de transfert de pointeur, valeur de variable : 2
On peut voir que le transfert de valeur et le transfert de pointeur des types de base de Go ne sont pas différent du C++, mais il n’a pas de concept de références variables. Alors, comment comprenez-vous les types de référence de Go ?

Types de référence de Go

Dans Go, les types de référence incluent des tranches, des dictionnaires, des canaux, etc. Prenons l'exemple du découpage. Le fait de passer une tranche est-il une référence ?

Par exemple :


package main
import (
  "fmt"
)
func main() {
  m1 := make([]string, 1)
  m1[0] = "test"
  fmt.Println("调用 func1 前 m1 值:", m1)
  func1(m1)
  fmt.Println("调用 func1 后 m1 值:", m1)
}
func func1 (a []string) {
  a[0] = "val1"
  fmt.Println("func1中:", a)
}
Le résultat de sortie est le suivant :

Valeur M1 avant d'appeler func1 : [test]

Dans func1 : [val1]

La valeur de m1 après l'appel de func1 : [val1]

La modification de la tranche dans la fonction affecte la valeur du paramètre réel. Cela signifie-t-il qu'il s'agit d'un passage par référence ?

En fait non. Pour répondre à cette question, il faut d'abord savoir si la fonction appelante slice m1 a changé. Nous devons d’abord comprendre la nature du découpage.

Une tranche est une description d'un fragment de tableau. Il contient un pointeur vers le tableau, la longueur du fragment.

En d'autres termes, ce que nous imprimons ci-dessus n'est pas la tranche elle-même, mais le tableau pointé par la tranche. Pour un autre exemple, vérifiez si la tranche a changé.


  package main
import (
  "fmt"
)
func main() {
  m1 := make([]string, 1)
  m1[0] = "test"
  fmt.Println("调用 func1 前 m1 值:", m1, cap(m1))
  func1(m1)
  fmt.Println("调用 func1 后 m1 值:", m1, cap(m1))
}
func func1 (a []string) {
  a = append(a, "val1")
  fmt.Println("func1中:", a, cap(a))
}
Le résultat de sortie est le suivant :

La valeur de m1 avant d'appeler func1 : [test] 1

In func1 : [test val1 ] 2

La valeur de m1 après l'appel de func1 : [test] 1

Ce résultat montre que la tranche n'a pas changé avant et après l'appel. Le soi-disant "changement" dans l'exemple précédent est en fait que les éléments du tableau pointés par le pointeur vers le tableau dans la tranche ont changé. Cette phrase est peut-être un peu gênante, mais elle est en fait vraie. Prouver une fois de plus que le passage de paramètres de types référence n'est pas un passage par référence.

Je veux bien comprendre qu'une tranche est une description d'un fragment de tableau. Il contient le pointeur vers le tableau et la longueur du fragment. Si vous êtes intéressé, vous pouvez lire cet article : http://www.jb51.net/kf/201604/499045.html. Découvrez le modèle de mémoire du découpage.

Résumé

Le résumé est très simple, et le langage doit aussi voir à travers le phénomène pour en voir l'essence. Il y a aussi la conclusion de cet article qu'il faut retenir :

Il n'y a pas de passage par référence dans Go.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn