2010-07-09 7 views
16

In C++,Was ist die Bedeutung der Rückkehr als Referenz?

function() = 10; 

funktioniert, wenn die Funktion eine Variable, die durch Bezugnahme zurückgibt.

Was sind die Anwendungsfälle davon?

+3

Es ist nicht notwendig, dass Syntax, wenn auch zu arbeiten. Sie können immer ein Proxy-Klassenobjekt zurückgeben, das seinen 'operator =' die Zuweisung hinter den Kulissen hat –

+1

Deshalb habe ich mich nie mit C++ herumgeschlagen ... Sie hören nie auf, neue Syntaxelemente zu finden, die Sie völlig umhauen. Überladen der Liebesoperator: | –

+0

Sie können sogar nach Wert zurückgeben und einem temporären zuweisen. Deshalb empfiehlt Scott Meyers, durch konstanten Wert zurückzukehren. – Philipp

Antwort

20

Der häufigste Fall ist die Implementierung von Dingen wie operator [].

struct A { 
    int data[10]; 
    int & operator[](int i) { 
     return data[i]; 
    } 
}; 

Ein weiterer Grund ist ein großes Objekt aus einer Klasse über eine Accesor Funktion zurück:

struct b { 
    SomeBigThing big; 
    const SomeBigThing & MyBig() const { 
     return big; 
    } 
}; 

, um den Kopieraufwand zu vermeiden.

2

Falls Sie haben eine Klasse, die eine andere Struktur enthält, kann es sinnvoll sein, direkt auf die enthaltene Struktur zu ändern:

struct S 
{ 
    int value; 
}; 

class C 
{ 
    public: 

     S& ref() { return m_s; } 

    private: 

     S m_s; 
}; 

Hier können Sie so etwas wie schreiben:

void foo() 
{ 
    C c; 

    // Now you can do that: 

    c.ref().value = 1; 
} 

Hinweis: In diesem Beispiel könnte es einfacher sein, m_s öffentlich zu machen, anstatt eine Referenz zurückzugeben.

0

std::vector hat operator[] die vec[n] = m sonst nicht zulassen würde.

3

Ein sehr normaler Anwendungsfall ist, wenn Sie ein Array wie Klasse schreiben. Hier sollten Sie die operator [] so zu überlasten, wie Sie a[0] = 10; In diesem Fall tun können Sie die Signatur sein wollen würde wie int& operator[](int index);

4

Getter/Setter zum Beispiel

class C 
{ 
    int some_param_; 
public: 
    int& param() { return some_param_; } 
    int const& param() const { return some_param_; } 
}; 

aber hier sollten Sie gehen mit some_param ein Wesen öffentliche int. Container stellen Funktionen bereit, die als Referenz zurückkommen, z. vector<T>::operator[], so dass Sie v[k] = x schreiben können.

+0

Und diese Implementierung ist schwer zu refaktorieren, wenn Sie some_param_ mit einem Objekt eines anderen Typs entfernen oder ersetzen müssen. – Basilevs

2

SO vermasselt meine Antwort

Sie brauchen nicht einmal einen Hinweis auf Rückkehr:

struct C { }; 

C f() { 
    return C(); 
} 

int main() { 
    C a; 
    f() = a; // compiles fine 
} 

Da dieses Verhalten ist ziemlich überraschend, Sie in der Regel einen const Wert oder einen const zurückgeben soll Referenz, es sei denn, der Benutzer hat eine vernünftige Absicht, das Ergebnis zu ändern.

2

Es kann sehr nützlich sein, wenn Accessoren

class Matrix 
{ 
    public: 
     //I skip constructor, destructor etc 

     int & operator()(int row, int col) 
     { 
     return m_arr[row + col * size]; 
     } 

    private: 
     int size; 
     int * m_arr; 
} 

Matrix m(10); 
m(1,0) = 10; //assign a value to row 1, col 0 
+0

Ich weiß nicht, warum, aber ich hasse Matrix-Klassen (und ich bin ein numerischer Analyst) –

7

Betrachten Sie den folgenden Code, MyFunction gibt einen Zeiger auf einen int Implementierung und Sie setzen einen Wert an den int.

int *i; 
i = MyFunction(); 
*i = 10; 

Jetzt, verkürzen

*(MyFunction()) = 10; 

Es tut genau das gleiche wie der erste Codeblock.

Sie können als nur einen Zeiger auf einer Referenz suchen, die immer dereferenziert wird. Also, wenn meine Funktion eine Referenz zurück - keinen Zeiger - in einen int der frist Codeblock

int &i; 
i = MyFunction(); 
i = 10; 

und die zweite würde

MyFunction() = 10; 

Dies ist geworden geworden wäre, was ich war auf der Suche nach

+2

Der Code, den Sie geschrieben ist nicht legal C++ - Referenzen initialisiert werden muss. –

1

Ein weiterer klassischer Fall:

class Foo { 
    Foo(); 
public: 
    static Foo& getSingleton(); 
}; 
0

Sie können auch Verfahren Verkettungs erreichen u (wenn Sie dies wünschen) sing Rückkehr durch Referenz.

class A 
{ 
public: 
    A& method1() 
    { 
     //do something 
     return *this; //return ref to the current object 
    } 
    A& method2(int i); 
    A& method3(float f); //other bodies omitted for brevity 
}; 

int main() 
{ 
    A aObj; 
    aObj.method1().method2(5).method3(0.75); 

    //or use it like this, if you prefer 
    aObj.method1() 
     .method2(5) 
     .method3(0.75); 
} 
0

Die named parameter idiom ist ein weiterer Anwendungsfall. Betrachten

class Foo 
{ 
public: 
    Foo(
     int lions, 
     float tigers, 
     double bears, 
     std::string zookeeper 
    ); 
}; 

Benutzer dieser Klasse müssen die Position der einzelnen Parameter

Foo foo(1, 2.0, 5, "Fred"); 

erinnern, die in der Kopfzeile, ohne hinzusehen nicht offensichtlich sein kann. Im Vergleich zu einem Schöpfer Klasse wie so

class CreateFoo 
{ 
friend class Foo; 
public: 
    CreateFoo(); 

    CreateFoo& lions(int lions) { 
     _lions = lions; 
     return *this; 
    } 

    CreateFoo& tigers(float tigers) { 
     _tigers = tigers; 
     return *this; 
    } 

    CreateFoo& bears(double bears) { 
     _bears = bears; 
     return *this; 
    } 

    CreateFoo& zookeeper(const std::string& zookeeper) { 
     _zookeeper = zookeeper; 
     return *this; 
    } 

private: 
    int _lions; 
    float _tigers; 
    double _bears; 
    std::string _zookeeper; 
}; 

, die dann von den Kunden verwendet werden können, wie so

Foo foo = CreateFoo(). 
    lions(1). 
    tigers(2.0). 
    zookeeper("Fred"). 
    bears(5) 
    ; 

vorausgesetzt Foo einen Konstruktor nimmt eine const CreateFoo& hat.

Verwandte Themen