[rückgabewert] optimale lsg gesucht
-
nochmal: wir ist klar, dass die übergabe mit ner referenz besser ist. aber hier geht es darum, dass mit diese option nicht zur verfügung steht. die struvt ist nur eine dummy-klasse und soll nur die problemstellung veranschaulichen.
ich habe leider nicht ide wahl, ich muss A, B oder C verwenden.gekärt werden müsste jetzt die frage mit ob A auch in dem von mir genannten weiten Bsp undefniert ist und vor allem würden mich die kopieroperationen interessieren (siehe topic)
-
Hallo
Also mein GCC meckert zu Recht wie ich erwartet habe
std::vector<int> Test() { return std::vector<int>(); } ... std::vector<int>& test = Test(); test.push_back(10);invalid initialization of non-const reference of type ... from a temporary of a type ...
Interessant ist das mit einer const Referenz kompiliert wird. Meines Erachtens sollte aber dann bei jedem Lesen von test auf ungültiger Speicher zugriffen werden.
bis bald
akari
-
Wenn eine Funktion ein Objekt zurückgibt, existiert dieses nur sehr sehr kurz und zwar nicht weiter, als bis die Zeile abgearbeitet ist (vereinfacht gesprochen
. Wenn du eine Referenz auf dieses Objekt setzt, zeigt die Referenz in irgendeinen Bereich, wo das Objekt gar nicht mehr ist (es wird ja kurz nach dem Funktionsaufruf kaputtgemacht).
Und Referenzen, die auf irgendwas ungültiges zeigen, sind scheiße, mit Verlaub
-
muffmolch schrieb:
gekärt werden müsste jetzt die frage mit ob A auch in dem von mir genannten weiten Bsp undefniert ist...
Grundsätzlich sehe ich keinen Grund warum dein Fall A jemals definiert sein sollte. Temporäre Ergebnise sind nach dem zuweisen undefiniert. Vermeide Kopien wo es möglich ist, aber unterbinde sie niemals wo es nötig ist.
cu André
-
Warum dir die Option nicht zur Verfuegung stehen sollte sei mal dahingestellt (ich kann mir kein Szenario vorstellen das sowas verbietet).
Warum version A undefiniert ist, nehme ich mal kurz auseinander:- Du definierst in getvector() einen vector tmp, der eigentlich nur genau innerhalb dieser Methode existiert.
- durch das return statement existiert tmp noch einen kleinen Tick laenger, naemlich um den Ergebniswert ggf einer anderen Variablen zuweisen zu koennen, wird danach aber doch zerstoert. (im Grunde wird eine temporaere Variable ohne Namen angelegt, die den inhalt von tmp kopiert. das wird aber meist wegoptimiert)
- durch die Zuweisung an eine Referenz (v) verweist diese Referenz auf tmp bzw. auf die temporaere Variable, die sofort nach der Zuweisung zerstoert wird. v ist also von Anfang an eine Referenz auf ein nichtmehr existierendes Objekt -> undefiniert.
-
Du kannst deinen vector in getVector mit new erstellen und dann den Pointer zurück geben und wieder löschen, wenn du ihn nicht mehr brauchst. es gibt auch noch diese auto_ptr, oder wie die heißen, die das wohl automatisch machen.
-
okay. das hilt mir schon mal enorm weiter... dann werde ich hier version B verwenden.
nur zur sicherheit. A ist aber erlaubt bzw. sogar pflicht (wenn nachhaltig memberdaten auf dieseunschöne weise ändern möchte) bei:struct X1{ vector<XYZ>& getVector() { return m_a; } vector<XYZ> m_a; }; int main() { X1 a; vector<XYZ>& vec = a.getVector(); }
-
lalallalala schrieb:
Du kannst deinen vector in getVector mit new erstellen und dann den Pointer zurück geben und wieder löschen, wenn du ihn nicht mehr brauchst. es gibt auch noch diese auto_ptr, oder wie die heißen, die das wohl automatisch machen.
stimmt... die auto_ptr idee ist gut. andernfalls generiert man sich leicht nen speicherloch.
-
pumuckl schrieb:
Warum dir die Option nicht zur Verfuegung stehen sollte sei mal dahingestellt (ich kann mir kein Szenario vorstellen das sowas verbietet).
Warum version A undefiniert ist, nehme ich mal kurz auseinander:- Du definierst in getvector() einen vector tmp, der eigentlich nur genau innerhalb dieser Methode existiert.
- durch das return statement existiert tmp noch einen kleinen Tick laenger, naemlich um den Ergebniswert ggf einer anderen Variablen zuweisen zu koennen, wird danach aber doch zerstoert. (im Grunde wird eine temporaere Variable ohne Namen angelegt, die den inhalt von tmp kopiert. das wird aber meist wegoptimiert)
- durch die Zuweisung an eine Referenz (v) verweist diese Referenz auf tmp bzw. auf die temporaere Variable, die sofort nach der Zuweisung zerstoert wird. v ist also von Anfang an eine Referenz auf ein nichtmehr existierendes Objekt -> undefiniert.danke für die erklärung
-
Schon gut, ich tippe einfach verdammt langsam

-
Hallo
muffmolch schrieb:
okay. das hilt mir schon mal enorm weiter... dann werde ich hier version B verwenden.
nur zur sicherheit. A ist aber erlaubt bzw. sogar pflicht (wenn nachhaltig memberdaten auf dieseunschöne weise ändern möchte) bei:struct X1{ vector<XYZ>& getVector() { return m_a; } vector<XYZ> m_a; }; int main() { X1 a; vector<XYZ>& vec = a.getVector(); }Ja das ist in Ordnung und sinnvoll. Aber eben auch ein großer Unterschied, da hier eine Referenz auf eine Membervariable zurückgegeben wird und nicht eine temporäre Kopie einer lokalen Variable.
bis bald
akari
-
@akiri
ist klar. ich hatte gehofft, dass eben die temporären im falle eines aliases soage bestehen bleiben, bis dieser den scope verläßt. aber das ist nun geklärt
ansonsten verwende ich aliase immer um v.a. den code übersichtlich zu machen.
daher eine frage am randevector< vector<int> > vec; ... vector<int>& internal_vec = vec[2]; internal_vec[3] = 4; //1 vec[2][4] =5; //21 und 2 führen beide eine zuweisung durch. ist 1 auch durch den direkten zugriff schneller als 2, denn dort muss er zuerst ja wieder vec[2] aufrufen.
-
Hallo
Naja bei einem einzigen Effektiven Zugriff hast du natürlich keinen Vorteil davon.
Wenn du aber mehrmals hintereinander auf den gleichen internal_vec zugreifen willst dann ist das sehr wohl effizienter.bis bald
akari
-
akari schrieb:
Hallo
Naja bei einem einzigen Effektiven Zugriff hast du natürlich keinen Vorteil davon.
Wenn du aber mehrmals hintereinander auf den gleichen internal_vec zugreifen willst dann ist das sehr wohl effizienter.
bis bald
akariselbstredend. sondern eben bei schleifen wie:
vector< vector<int> > vec; ... for(int i=(int)vec.size()-1; i>=0; ++i){ vector<int>& internal_vec[i]; for(int j=(int)vec[i].size()-1; i>=0; ++j) internal_vec[j] = i*j; }
-
muffmolch schrieb:
Frage: Welche Variante ist Laufzeitechnisch und v.a. speichertechnisch unter der Anahme von laaaaangen, speicherintensiven vektoren zu bevorzugen?
Variante

vector<XYZ> vec; X a; a.getVector().swap(vec);Dass das meist nicht gemacht wird, bedarf keiner Erklärung. In gewisser Weise ist das eine Art manuelles move - mit C++0x wird das unnötig werden.