2009-03-23 11 views
15

In einem Projekt, das ich halte, sehe ich eine Menge Code, wie dies für einfache get/set MethodenWas ist die Verwendung von Const-Referenzen auf primitive Typen?

const int & MyClass::getFoo() { return m_foo; } 

void MyClass::setFoo(const int & foo) { m_foo = foo; } 

Was der Punkt ist, dass anstelle des folgenden dabei?

int MyClass::getFoo() { return m_foo; } // Removed 'const' and '&' 

void MyClass::setFoo(const int foo) { m_foo = foo; } // Removed '&' 

Passing einen Verweis auf eine primitive Art sollte die gleiche (oder mehr) Aufwand erfordern als den Typ der Wert vorbei selbst, nicht wahr?
Es ist nur eine Nummer nach allem ...
Ist das nur ein paar versuchte Mikro-Optimierung oder gibt es einen echten Vorteil?

Antwort

20

Der Unterschied ist, dass wenn Sie dieses Ergebnis in eine Referenz selbst erhalten, Sie die Änderungen der Integer-Elementvariable in Ihrem eigenen Variablennamen verfolgen können, ohne die Funktion aufzurufen.

const &int x = myObject.getFoo(); 
cout<<x<<endl; 
//... 
cout<<x<<endl;//x might have changed 

Es ist wahrscheinlich nicht die beste Design Wahl, und es ist sehr gefährlich, eine Referenz (const oder nicht), falls eine Variable zurückzugeben, die von Umfang befreit wird zurückgegeben. Wenn Sie also eine Referenz zurückgeben, achten Sie darauf, dass es sich nicht um eine Variable handelt, die den Gültigkeitsbereich verlässt.

Es gibt auch einen kleinen Unterschied für den Modifikator, aber wahrscheinlich auch nicht etwas, das es wert ist oder gemacht wurde.

void test1(int x) 
{ 
    cout<<x<<endl;//prints 1 
} 

void test2(const int &x) 
{ 
    cout<<x<<endl;//prints 1 or something else possibly, another thread could have changed x 
} 

int main(int argc, char**argv) 
{ 
    int x = 1; 
    test1(x); 
    //... 
    test2(x); 
    return 0; 
} 

Das Endergebnis ist also, dass Sie Änderungen erhalten, auch nachdem die Parameter übergeben wurden.

+0

"Es ist sehr gefährlich, eine Referenz (const oder nicht) zurückzugeben" - Ich bin gespannt, wie kommen Sie dann zu schwereren Werten zurück? Vielleicht ist die Notwendigkeit ein Zeichen von schlechtem Design, aber ich tendiere dazu, Strings by const ref zurückzugeben. –

+0

@me - Ich sage nicht, Strings sind Schwergewicht, ich bevorzuge es, den (zugegebenermaßen geringen) Aufwand zu vermeiden, sie zu kopieren. –

+0

Auf diese Weise müssen Sie über die Lebensdauer des Objekts nachdenken. Das kann für komplexe Datentypen wert sein, aber nicht für primitive, die zu den gleichen Kosten wie Referenzen kopiert werden. – sharptooth

5

Der Hauptunterschied zwischen der Rückgabe eines Werts und der Rückgabe einer Konst-Referenz besteht darin, dass Sie diese Referenz dann const_cast und den Wert ändern können.

Es ist ein Beispiel für schlechtes Design und ein Versuch, ein intelligentes Design zu schaffen, bei dem einfaches und prägnantes Design mehr als genug wäre. Anstatt nur einen Wert zurückzugeben, lässt der Autor den Leser des Codes darüber nachdenken, welche Absicht er hätte haben können.

2

Ich denke, dass diese Art von Code geschrieben wird, die das Konzept der Verweise missverstanden haben und es für alles einschließlich primitiver Datentypen verwenden. Ich habe auch einen Code wie diesen gesehen und sehe keinen Vorteil darin.

0

Es hat keinen Sinn und Nutzen außer

void MyClass::setFoo(const int foo) 
void MyClass::setFoo(const int& foo) 

wie dann werden Sie nicht in der Lage sein, ‚foo‘ Variable innerhalb Implementierung ‚setFoo‘ wiederzuverwenden. Und ich glaube, dass 'int &' nur deshalb ist, weil Guy sich nur daran gewöhnt, alle Dinge durch const-Referenz zu übergeben, und daran ist nichts falsch.

4

Es gibt nicht viel Vorteil. Ich habe das in Framework oder Makro generierten Getter und Setter zuvor gesehen. Der Makrocode unterschied nicht zwischen Primitiv- und Nicht-POD-Typen und verwendete const type& auf der ganzen Linie für Setter. Ich bezweifle, dass es sich um ein Effizienzproblem oder ein echtes Missverständnis handelt; Wahrscheinlichkeiten sind dies ein Konsistenzproblem.

+0

+1 für den Aufruf eines Konsistenzproblems. –

7

Für mich ist es ein Fehler, eine const Referenz für Primitive zu übergeben.Entweder müssen Sie den Wert ändern, und in diesem Fall übergeben Sie eine nicht-const Referenz, oder Sie müssen nur auf den Wert zugreifen und in diesem Fall übergeben Sie eine const.

Const Referenzen sollte nur für komplexe Klassen verwendet werden, wenn das Kopieren von Objekten ein Leistungsproblem sein kann. Im Falle von Primitiven müssen Sie, sofern Sie den Wert der Variablen nicht ändern müssen, keine Referenz übergeben. Der Grund dafür ist, dass Referenzen mehr Rechenzeit als nicht-Referenzen nehmen, da mit Referenzen, das Programm in einer Tabelle nachschlagen muss die Adresse des Objekts zu finden. Wenn diese Nachschlagezeit kürzer als die Kopierzeit ist, sind Referenzen eine Verbesserung.

Allgemeinen Ints und Adressen haben die gleiche Byte Länge in Low-Level-Implementierungen. Der Zeitpunkt des Kopierens eines int als Rückgabewert für eine Funktion entspricht daher dem Zeitpunkt des Kopierens einer Adresse. Aber in dem Fall, in dem ein int zurückgegeben wird, wird keine Suche durchgeführt, daher wird die Leistung erhöht.