2010-03-04 6 views
28

In einer C++ Funktion wie folgt aus:In C++, was bedeutet & nach dem Rückgabetyp einer Funktion?

int& getNumber(); 

was bedeutet der &? Ist es anders aus:

int getNumber(); 
+4

Die '&' im Grunde sagt, dass ich die Rückkehr ** Adresse ** wobei der zurückgegebene Wert gespeichert wird (dh er gibt die "Referenz" der Ganzzahl zurück), während "int getNumber()" den "Wert" der von der Funktion zurückgegebenen Ganzzahl zurückgibt. Eine Sache ist, dass, wenn die Referenz-Integer auf einen NULL zeigt, Sie möglicherweise einen Segmentierungsfehler haben, während die andere Funktion eine 0 zurückgibt; –

+6

Eine Sache, die niemand erwähnt: Niemals einen Verweis auf eine lokale Variable zurückgeben! Sie erhalten undefinierte Ergebnisse, wenn die Variable am Ende der Funktion den Gültigkeitsbereich verlässt. –

+4

Wenn "getNumber()" eine öffentliche Methode einer Klasse ist, die eine private Membervariable dieser Klasse zurückgibt, verwenden Sie nicht die Version, die eine Referenz zurückgibt. Andernfalls können Benutzer Ihrer Klasse den Wert dieses privaten Mitglieds außerhalb der Klasse ändern. Mit anderen Worten, das private Mitglied wird nicht mehr von der Klasse gekapselt. –

Antwort

24

Ja, die int& Version gibt einen Verweis auf eine int. Die int Version gibt einen int Wert zurück.

Siehe the section on references in der C++ FAQ

+1

Downvoter Pflege zu erklären? –

+23

Anstatt das OP durch ein riesiges Dokument zu lesen, das seine Frage beantwortet, aber nur auf Umwegen, warum schreiben Sie nicht ein 10-Zeilen-Programm, das den Unterschied zeigt. –

2

"&" bedeutet Referenz, in diesem Fall "Referenz auf int".

7

Ja, das ist anders.

Die & bedeutet, dass Sie eine Referenz zurückgeben. Sonst gibt es eine Kopie zurück (gut, manchmal optimiert der Compiler es, aber das ist nicht das Problem hier).

Ein Beispiel ist Vektor. Der Operator [] gibt & zurück. Dies ermöglicht es uns:

my_vector[2] = 42; 

Das würde nicht mit einer Kopie arbeiten.

+1

+1 für ein sinnvolles Beispiel, das keine globalen Variablen verwendet! @Johan, es würde nicht funktionieren, weil Sie entweder einen Stapelspeicherort oder eine Kopie des Standorts im Vektor zuweisen würden ... –

2

Dies bedeutet, dass es sich um einen Referenztyp handelt. Was ist eine Referenz?

Wikipedia:

In der Programmiersprache C++, ist eine Referenz ein einfaches Referenzdatentyp, der weniger leistungsfähig ist, aber sicherer als der Typ Zeiger geerbt von C. Der Name C++ Referenz zu Verwirrung führen kann, wie in Computern Wissenschaft Eine Referenz ist ein allgemeiner Konzeptdatentyp, wobei Zeiger und C++ Referenzen spezifische Implementierungen von Referenzdatentypen sind. Die Erklärung der Form:

Typ & Bezeichnung

wo ein Typ ist, und ist eine Kennung, deren Typ Referenz auf.

Beispiele:

  1. int A = 5;
  2. int & rA = A;
  3. extern int & rB;
  4. int & foo();
  5. Leere Bar (int & rP);
  6. Klasse MyClass {int & m_b;/* ...* /};
  7. int funcX() {return 42; }; int (& xFunc)() = funcX;

Hier rA und rB sind vom Typ "reference in int" foo() ist eine Funktion, einen Verweis zurück auf int, bar() ist eine Funktion mit einem Bezugsparameter, was Verweis auf int, MyClass ist eine Klasse mit einem Mitglied, das ist Verweis auf int, funcX() ist eine Funktion, die einen int zurückgibt, xFunc() ist ein Alias ​​für funcX.

Rest der Erklärung ist here

+1

Leider ist Wikipedia hier falsch. Es ist nicht sicherer als ein Zeiger, es ist genau syntaktischer Zucker für einen const Zeiger (ich meine nicht Zeiger zu const Daten). –

+2

Aber es kann viele Compilerfehler vermeiden. Das ist was Wikipedia bedeutet. – Shayan

+1

Ich habe noch nie von einem einzigen Compilerfehler gehört, der für Zeiger und Referenzen grundlegend anders war. –

1

Es bedeutet, es ist eine reference in einen int zurückkehrt, kein int selbst.

1

Es ist eine Referenz, die genau wie ein Zeiger ist, außer Sie müssen keinen Zeiger-Dereferenzierungsoperator (* oder ->) damit verwenden, die Zeigerdereferenzierung ist impliziert.

Beachten Sie insbesondere, dass alle Bedenken bezüglich der Lebensdauer (z. B. dass eine Stapelvariable nicht nach Adresse zurückgegeben wird) immer noch so behandelt werden müssen, als ob ein Zeiger verwendet würde.

+1

Referenzen können mit Zeigern verglichen werden, und als Zeiger gedacht werden, sind aber definitiv nicht "genau wie Zeigern". Wenn Sie beispielsweise einer Referenz zuweisen, ändert sich der auf * bezogene Wert anstelle der Referenz selbst. Darüber hinaus müssen Referenzen zum Zeitpunkt ihrer Erstellung mit einem Wert versehen werden und während ihrer gesamten Lebensdauer auf denselben Wert verweisen. – Thomas

+1

@Thomas: Referenzen werden bei der Erstellung kein Wert zugewiesen, sie sind mit einer Adresse verknüpft - einem Zeiger. Ja, sie können nicht mit einer neuen Adresse reassoziiert werden, aber auch kein const-Zeiger. Die Zuweisung über eine Referenz entspricht genau der Zuweisung über einen Zeiger, außer dass Sie für die Pointer-Syntax ein zusätzliches Sternchen benötigen, was ich unter "Pointer-Dereferenzierung ist impliziert" verstehe. Eine Referenz ist nicht mehr und nicht weniger als ein const-Zeiger, gemischt mit ein wenig syntaktischem Zucker. –

4

int& getNumber(): Die Funktion gibt eine Ganzzahl als Referenz zurück.

int getNumber(): Die Funktion gibt eine ganze Zahl als Wert zurück.

Sie unterscheiden sich in einigen Punkten und einer der interessanten Unterschiede ist, dass der 1. Typ auf der linken Seite der Zuweisung verwendet werden kann, was mit dem 2. Typ nicht möglich ist.

Beispiel:

int global = 1; 

int& getNumber() { 
     return global; // return global by reference. 
} 

int main() { 

     cout<<"before "<<global<<endl; 
     getNumber() = 2; // assign 2 to the return value which is reference. 
     cout<<"after "<<global<<endl; 

     return 0; 
} 

Ouptput:

before 1 
after 2 
4

Die erste Version ermöglicht es Ihnen , zu schreiben, die wahrscheinlich nicht das, was Sie wollen. Die Rückgabe von Referenzen ist sehr nützlich, wenn Sie operator[] für Ihre eigenen Containertypen überladen. Es ermöglicht Ihnen, container[9] = 42 zu schreiben.

+1

Erklären Sie, warum es für Container funktioniert und Sie eine perfekte Antwort haben. –

25

Es ist anders.

int g_test = 0; 

int& getNumberReference() 
{ 
    return g_test; 
} 

int getNumberValue() 
{ 
    return g_test; 
} 

int main() 
{ 
    int& n = getNumberReference(); 
    int m = getNumberValue(); 
    n = 10; 
    cout << g_test << endl; // prints 10 
    g_test = 0; 
    m = 10; 
    cout << g_test << endl; // prints 0 
    return 0; 
} 

die getNumberReference() liefert eine Referenz, unter der Haube wie ein Zeiger ist es, dass auf eine ganzzahlige Variable zeigt. Jede Änderung, die für die Referenz gilt, gilt für die zurückgegebene Variable.

Die getNumberReference() ist auch ein Link Wert, und kann daher wie folgt verwendet werden:

getNumberReference() = 10; 
5

Der Unterschied ist, dass es ohne die &, was man bekommt wieder eine Kopie des zurückgegebenen int ist, geeignet um in andere Routinen zu wechseln, mit Dingen zu vergleichen oder in Ihre eigene Variable zu kopieren.

Mit der &, was Sie zurück erhalten, ist im Wesentlichen die Variable, die die zurückgegebene Ganzzahl enthält.Das bedeutet Sie es tatsächlich auf der linken Seite einer Zuweisung setzen können, etwa so:

getNumber() = 200;