Rückgabe einer Membervariablen als Referenz
-
Ich find's ja sauberer den Member direkt public zu machen, statt da ne Referenz zurückzugeben aus ner Funktion, ist im Prinzip das gleiche.
-
Decimad schrieb:
Ich find's ja sauberer den Member direkt public zu machen, statt da ne Referenz zurückzugeben aus ner Funktion, ist im Prinzip das gleiche.
Nein, ist es nicht.
class Blubb { std::string s; public: std::string const& blobb() const { return s; } };
-
Decimad schrieb:
[...] ist im Prinzip das gleiche.
-
cooky451: OK. Wenn ich es richtig verstehe:
Es wird zwar keine Referenz zurückgegeben. Trotzdem höchst fragwürdige Übergabe einer temporären Kopie an eine Referenzvariable möglich...
Eines würde mich aber noch interessieren: Wenn ich den Rückgabewert nicht als Referenz deklariere, heißt das dann automatisch, dass auch tatsächlich kopiert wird? Oder anders gefragt: Können Compiler erkennen, wann eine Kopie eigentlich überflüssig ist? Können Compiler überflüssige Kopiervorgänge "wegoptimieren"?
-
Jau, können sie und machen die meisten auch. Das nennt sich dann "return value optimization" (RVO) und "named return value optimization" (NRVO). Du musst ggf. die Optimierungseinstellungen deines Compilers anpassen, aber im Release Modus mit höchstmöglichen Optimierungseinstellungen sollte jeder halbwegs gute Compiler das wegoptimieren.
Ob optimiert werden kann weiß der Compiler am besten, das bekommst du als Anwender oft nicht mit. Um sicherzugehen könnte man den erzeugten Assembler Code angucken und den überprüfen. Manchestd::string
Implementationen benutzen Copy-On-Write Techniken, bei denen tatsächlich nur Pointer kopiert werden und erst beim ersten schreibenden Zugriff eine Kopie des Originals erstellt wird. Das ist allerdings implementationsabhängig und vom Standard nicht vorgeschrieben.
-
keine_ahnung98258495 schrieb:
Können Compiler überflüssige Kopiervorgänge "wegoptimieren"?
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
http://en.wikipedia.org/wiki/C%2B%2B11#Rvalue_references_and_move_constructors <- C++11Edit:
keine_ahnung98258495 schrieb:
Übergabe einer temporären Kopie an eine Referenzvariable
Referenzen != Pointer, zumindest was die Sprachsemantik angeht. Denn mit Referenzen geht das AFAIK nicht, da diese ja sofort initialisiert werden müssen und somit auch nicht außerhalb des Scopes definiert werden können. Solche Konstrukte funktionieren also nur über Pointer, nicht aber über Referenzen.
(Mit Membervariablen funktioniert das trotzdem, aber das ist noch mal eine andere Geschichte.)
class A { std::string& s_; public: A(std::string& s) : s_(s) {} void print() { std::cout << s; } }; int main() { A a(std::string("Hm..")); a.print(); // Autsch }
-
Swordfish:
Was hat denn bitte die Rückgabe einer Referenz auf einen Datenmember mit Datenkapselung zu tun? Die Referenz kann nur auf einen Datenmember der Klasse zeigen (wäre es eine lokale Variable innerhalb der Methode -> Bam). Jetzt erzähl mir hier bitte mal nix von wegen ich hätte Datenkapselung nicht verstanden. Bevor ich da eine Referenz zurückgebe um ach so viel Performance rauszukitzeln, mach ich den Member public, punkt aus.
Natürlich wäre meine erste Wahl, die Implementierung hinter der Schnittstelle verbergen (fällt aber gerade aus, weil das nicht das Thema ist offenbar). Mit dieser Referenzsache legt ihr ja praktisch die Implementierung offen (und man sorgt für Lebenszeit-Probleme).
-
cooky451: Vielen Dank! Ich habe aber noch ein Problem mit deinem letzten Beispiel: Dem Konstruktor von A soll doch eine Referenz auf ein
std::string
übergeben werden. Muss da nicht ein left-value übergeben werden? Irgendwie kriege ich das nicht kompiliert...no matching function for call to ‘A::A(std::string)’
Wenn ich mir zuvor ein left-value in Form einer string-Variablen anlege, und die dann übergebe, läuft es. Aber dann sieht man irgendwie nicht die Problematik...
-
Decimad schrieb:
Swordfish:
Was hat denn bitte die Rückgabe einer Referenz auf einen Datenmember mit Datenkapselung zu tun? Die Referenz kann nur auf einen Datenmember der Klasse zeigen (wäre es eine lokale Variable innerhalb der Methode -> Bam). Jetzt erzähl mir hier bitte mal nix von wegen ich hätte Datenkapselung nicht verstanden. Bevor ich da eine Referenz zurückgebe um ach so viel Performance rauszukitzeln, mach ich den Member public, punkt aus.Die Übergabe als Referenz (besonders als Referenz auf const) hat nichts mit Datenkapselng zu tun - die Definition als public dagegen schon. (die Übergabe als "einfache" Referenz ist da grenzwertig)
-
keine_ahnung98258495 schrieb:
Aber dann sieht man irgendwie nicht die Problematik...
Ja, da fehlt ein const. http://ideone.com/PyUN4
Lustigerweise kompiliert es mit MSVC auch ohne.
-
cooky451: Ah, jetzt hab ich's. Finde ich interessant...