Referenzen als Rückgabetyp bei inline-Methoden
-
Hallo zusammen,
Ich habe eine wahrscheinlich eher triviale Frage. Ich habe aber dennoch nirgendwo die passende Antwort gefunden, weshalb ich sie nun hier stelle.
Ich würde also gerne wissen, ob bei einer inline-Methode, welche einen Wert zurück gibt, eigentlich auch tatsächlich zur Laufzeit eine Variable angelegt werden muss - oder wird diese bereits zur Übersetzungszeit angelegt? Bzw. etwas anders formuliert: Ist die zweite der unteren zwei Varianten möglicherweise "schneller"?
1. Variante (mit Variable):
class Pin { const static int total_number_of_pins=200; static bool *level[total_number_of_pins+1]; const int pin_number; public: explicit Pin(const int &pin_number) : pin_number(this->pin_number) { this->level=static_cast<bool *>(MapMemory()); }; const bool & get_level() const; //explicit inline }; inline const bool & Pin::get_level() { return *(this->level+this->pin_number); }2. Variante (mit Referenz):
class Pin { const static int total_number_of_pins=200; static bool *level[total_number_of_pins+1]; const int pin_number; public: explicit Pin(const int &pin_number) : pin_number(this->pin_number) { this->level=static_cast<bool *>(MapMemory()); }; const bool get_level() const; //explicit inline }; inline const bool Pin::get_level() { return *(this->level+this->pin_number); }
-
Die Versionen sind mit Compileroptimierungen exakt gleich schnell.
Aber um mal auf die Variante ohne Optimierungen einzugehen:
"Reservierungen" auf dem Stack sind nichts weiter als Subtraktionen, das geht super schnell. Zudem liegt da alles hübsch hintereinander (das ist schön für den Cache) und Reservierungen erfolgen in Frames, nicht einzeln.Die Referenz dagegen, im Falle dass sie nicht wegoptimiert wird, stellt nichts anderes als ein Pointer dar. Das ist eine Indirektion, und im schlimmsten Fall hast du auch noch einen Cache-Miss.
Daher: Alles was kleiner oder gleich 8 Byte groß ist (vielleicht auch noch mit 16/32, da fängt es aber an knapp zu werden), per value übergeben und zurückgeben. Referenzen machen da nur Sinn, wenn du lvalues brauchst.
PS: Das inlining machen Compiler heutzutage schon ganz gut alleine, da brauchst du nicht nachhelfen. Allerdings brauchst du es hier tatsächlich, um der one-definition-rule auszuweichen. (Wenn das so im Header steht.)
PPS: const auf rvalues macht sehr wenig Sinn, die sind per Definition sowas von const, da gibts nichts mehr zu verconsten. Mal versucht nem value-Rückgabewert etwas zuzuweisen?
PPPS: Du solltest das this-> aus Stilgründen nur schreiben wenn du es brauchst. (Hier nie.)
PPPPS: level sollte hier eine eigene Klasse und kein Teil von Pin sein. Schachfiguren besitzen ja auch nicht das Brett, sie stehen nur drauf.
-
Hey cooky451,
Vielen Dank für die Antwort, welche mein Problem eigentlich mehr als klärt.Einzig den letzten Hinweis verstehe ich nicht so ganz.
cooky451 schrieb:
PPPPS: level sollte hier eine eigene Klasse und kein Teil von Pin sein. Schachfiguren besitzen ja auch nicht das Brett, sie stehen nur drauf.
Der Pin besitzt sein Level (High oder Low) aber sehr wohl, oder?
-
DERBENUTZER schrieb:
Der Pin besitzt sein Level (High oder Low) aber sehr wohl, oder?
Nein. Ein Level besitzt vielleicht die Pins, aber nicht umgekehrt.
-
Ich finde ja die Pointer-Arithmetik hier etwas suspekt:
return *(this->level+this->pin_number);Warum nicht
return level[pin_number];?
Dann würde auch auffallen, dass da ein bool* rauskommt, kein bool.
-
HyperSonic schrieb:
Ich finde ja die Pointer-Arithmetik hier etwas suspekt:
return *(this->level+this->pin_number);Warum nicht
return level[pin_number];?
Dann würde auch auffallen, dass da ein bool* rauskommt, kein bool.
Das ist in der Tat nicht gerade vom Feinsten. Es handelt sich aber sowieso nur um ein Beispiel ohne Sinn oder Zweck.