Heim >Backend-Entwicklung >Python-Tutorial >Go-Sprachvergleich C++-Referenzparameterübergabe

Go-Sprachvergleich C++-Referenzparameterübergabe

巴扎黑
巴扎黑Original
2017-09-02 11:16:131541Durchsuche

In diesem Artikel wird hauptsächlich erläutert, ob Go über Parameterübergabe per Referenz verfügt (im Vergleich zu C++). Freunde, die dies benötigen, können sich auf

Drei Parameterübergabemethoden in C++

Wertübergabe:

Die gebräuchlichste Methode zur Parameterübergabe sind Kopien der tatsächlichen Parameter in der Funktion hat keinen Einfluss auf formale Parameter außerhalb der Funktion. Im Allgemeinen wird die Wertübergabe verwendet, wenn Parameter innerhalb einer Funktion geändert werden, ohne dass sich dies auf den Aufrufer auswirkt.

Zeigerübergabe

Der formale Parameter ist ein Zeiger auf die Adresse des tatsächlichen Parameters, wenn der Inhalt, auf den der formale Parameter zeigt, manipuliert wird In der Funktion wird der eigentliche Parameter selbst geändert.

Übergabe als Referenz

In C++ ist eine Referenz ein Alias ​​für eine Variable, die eigentlich dasselbe ist und auch an derselben Adresse im Speicher existiert. Mit anderen Worten: Wo immer eine Referenz manipuliert wird, wird die referenzierte Variable ganz direkt manipuliert.

Sehen Sie sich die Demo unten an:


#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;
}
Das Ausgabeergebnis ist wie folgt:

Variable tatsächliche Adresse: 0x28feac, Variable Wert: 5

Wertübertragung, Variablenadresse: 0x28fe90, Variablenwert: 5
Nach dem Wertübertragungsvorgang, Variablenwert: 5
Aktuelle Variablenadresse: 0x28feac, Variablenwert: 5
Zeigerübertragung, Variable Adresse: 0x28feac, Variablenwert: 5
Nach der Zeigerübertragungsoperation, Variablenwert: 6
Aktuelle Variablenadresse: 0x28feac, Variablenwert: 6
Zeigerübertragung, Variablenadresse: 0x28feac, Variablenwert: 6
Nach der Referenzübertragungsoperation,Variablenwert: 7

Parameterübergabe in Go

Das Obige stellt die drei Parameterübergabemethoden von vor C++, Wertübergabe und Zeigerübergabe sind leicht zu verstehen. Verfügt Go also auch über diese Methoden zur Parameterübergabe? Dies hat zu Kontroversen geführt, aber im Vergleich zum Konzept der Referenzübergabe in C++ können wir sagen, dass Go über keine Methode zur Referenzübergabe verfügt. Warum sage ich das? Weil Go das Konzept der Variablenreferenzen nicht hat. Go verfügt jedoch über Referenztypen, die später erläutert werden.

Sehen wir uns zunächst ein Beispiel für die Übergabe von Werten und Zeigern in Go an:


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)
}
Das Ausgabeergebnis lautet wie folgt:

Die tatsächliche Adresse der Variablen: 0xc04203c1d0 Variablenwert: 1

Wertübertragung, Variablenadresse: 0xc04203c210 Variablenwert: 2
Nach dem Wertübertragungsvorgang Variablenwert: 1
Aktuelle Variablenadresse: 0xc04203c1d0 Variable Wert: 1
Zeigerübertragung, Variablenadresse: 0xc04203c1d0 Variablenwert: 2
Nach der Zeigerübertragungsoperation Variablenwert: 2
Es ist ersichtlich, dass die Wertübertragung und Zeigerübertragung der Grundtypen von Go nein sind unterscheidet sich von C++, verfügt jedoch über kein Variablenreferenzkonzept. Wie verstehen Sie also die Referenztypen von Go?

Gos Referenztypen

In Go umfassen Referenztypen Slices, Wörterbücher, Kanäle usw. Nehmen Sie als Beispiel das Slicing. Ist die Übergabe eines Slice eine Referenz?

Zum Beispiel:


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)
}
Das Ausgabeergebnis lautet wie folgt:

M1-Wert vor Aufruf von func1: [test]

In func1: [val1]

Der Wert von m1 nach dem Aufruf von func1: [val1]

Die Änderung am Slice in der Funktion wirkt sich auf den Wert des tatsächlichen Parameters aus. Bedeutet das, dass es sich hierbei um eine Referenzübergabe handelt?

Eigentlich nicht. Um diese Frage zu beantworten, müssen wir zunächst herausfinden, ob sich die aufrufende Funktionsscheibe m1 geändert hat. Zuerst müssen wir die Natur des Schneidens verstehen.

Ein Slice ist eine Beschreibung eines Array-Fragments. Es enthält einen Zeiger auf das Array, die Länge des Fragments.

Mit anderen Worten, was wir oben drucken, ist nicht das Slice selbst, sondern das Array, auf das das Slice zeigt. Überprüfen Sie in einem anderen Beispiel, ob sich das Slice geändert hat.


  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))
}
Das Ausgabeergebnis ist wie folgt:

Der Wert von m1 vor dem Aufruf von func1: [test] 1

In func1: [test val1 ] 2

Der Wert von m1 nach dem Aufruf von func1: [test] 1

Dieses Ergebnis zeigt, dass sich der Slice vor und nach dem Aufruf nicht geändert hat. Die sogenannte „Änderung“ im vorherigen Beispiel besteht tatsächlich darin, dass sich die Elemente des Arrays, auf die der Zeiger auf das Array im Slice zeigt, geändert haben. Dieser Satz mag etwas umständlich sein, aber er ist tatsächlich wahr. Dies beweist einmal mehr, dass die Parameterübergabe von Referenztypen keine Referenzübergabe ist.

Ich möchte vollständig verstehen, dass ein Slice eine Beschreibung eines Array-Fragments ist. Es enthält den Zeiger auf das Array und die Länge des Fragments. Wenn Sie interessiert sind, können Sie diesen Artikel lesen: http://www.jb51.net/kf/201604/499045.html. Erfahren Sie mehr über das Speichermodell des Slicings.

Zusammenfassung

Die Zusammenfassung ist sehr einfach, und die Sprache muss auch das Phänomen durchschauen, um das Wesentliche zu erkennen. Es gibt auch die Schlussfolgerung dieses Artikels, an die man sich erinnern muss:

In Go gibt es keine Pass-by-Referenz.

Das obige ist der detaillierte Inhalt vonGo-Sprachvergleich C++-Referenzparameterübergabe. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn