Nexus schrieb:
hustbaer schrieb:
std::vector kann eben (noch) keine move-Sekamtik, und kann daher relativ teuer als Returnwert sein (weil u.U. kopiert wird).
Hmm. Letztes Mal wurde mir mehr oder weniger gesagt, RVO würde hier das Richtige tun. Vielleicht antwortete auch deshalb niemand mehr spezifisch, als ich nochmals nachfragte.
Ich bin nach wie vor der Ansicht, man sollte sich bei Rückgabetypen nicht darauf verlassen, dass keine unnötigen Kopien angelegt werden. Also bei grösseren Objekten eher Referenzparameter benutzen. Wie sieht es nun wirklich aus?
kannst du dich nicht darauf verlassen
gibt es Fälle, wo (N)RVO garnicht greifen kann:
void foo()
{
std::vector<std::string> vec;
// ... use vec ...
vec = bar(); // keine Chance für (N)RVO!
// ... use vec ...
}
(Mit "greifen kann" meine ich nicht dass RVO nicht trotzdem verwendet werden kann um das Temporary zu initialisieren, sondern dass danach trotzdem der assignment operator laufen muss, und der Aufruf damit erst wieder unnötig teuer wird)
Natürlich könnte man solche Stellen umschreiben, so dass (N)RVO wieder möglich ist:
void foo()
{
std::vector<std::string> vec;
// ... use vec ...
std::vector<std::string> temp(bar());
vec.swap(temp);
// ... use vec ...
}
Der Nachteil ist allerdings, dass man daran denken muss, es immer so zu machen.
----
z.T. auto_ptr : ja, könnte man auch verwenden. Ich persönlich verwende halt lieber shared_ptr als auto_ptr . Andrerseits hat auto_ptr einen klaren Vorteil gegenüber shared_ptr : man bekommt die Ownership "wieder zurück" wenn man möchte ( T* myPrecious = autoPtr.release(); ).
Ob so eine Optimierung Sinn macht oder nicht ist natürlich wieder die andere Frage. Wenn man genau eine Ebene hat durch die der std::vector als Returnwert durchgereicht wird, und die Daten ursprünglich z.B. aus einer Datenbank kommen, dann wird man den Unterschied vermutlich nicht spüren! Und sollte daher auch eher auf solche Optimierungen zerzichten