unique_ptr Funktionsargument
-
Sone schrieb:
Das ist was anderes. Wieso überhaupt einen **Smart-**Pointer als Funktionsparameter, wenn diese den Besitz nicht in irgendeiner Weise übernimmt?
Das war für deine in-klassen-unique-pointer Pauschalaussage, die du völlig ohne Begründung genannt hast. Da will ich dir einmal was gutes tun...naja. Das hab ich davon. Nevermore.
-
void f(std::unique_ptr<int> u);Geht das überhaupt? Ich dachte man kann von einem unique_ptr keine Kopie machen.
-
TNA schrieb:
void f(std::unique_ptr<int> u);Geht das überhaupt? Ich dachte man kann von einem unique_ptr keine Kopie machen.
Exakt meine Frage auf der ersten Seite, auch dort beantwortet.
-
Deshalb frage ich, aber ich habe nicht gesehen das jemand direkt darauf geantwortet hätte oder ich verstehe zumindest die Antwort nicht.
-
void f(std::unique_ptr<int>&& u)Eine RValue-Referenz als Funktionsparameter mache ich doch wenn ich Ownership übertragen möchte oder? Also der Aufrufer weiß an der Stelle, dass er das übergebene Objekt nicht weiter benutzen kann oder darf oder?
-
TNA schrieb:
Eine RValue-Referenz als Funktionsparameter mache ich doch wenn ich Ownership übertragen möchte oder?
Nein, sondern wenn nur RValues als Argumente akzeptiert werden sollen. Typischerweise sind das temporäre Objekte oder Rückgabewerte von
std::move(). Am ehesten brauchst du RValue-Referenz-Parameter bei Move-Konstruktor und Move-Zuweisungsoperator (oder wenn du spezifisch optimieren willst, um Moves zu vermeiden). Ansonsten würde ich Pass By Value grundsätzlich vorziehen, da es flexibler ist und in vielen Fällen Codeduplizierung (Überladung fürT&&undconst T&) vermeidet.Wichtig ist zu sehen, dass RValue-Referenz und Move-Semantik verschiedene Konzepte sind. Zwar hängen sie insofern zusammen, als Move-Semantik auf Klassenebene über RValue-Referenzen implementiert wird; doch viele Moves geschehen, ohne dass ein
&&in der Funktion oder im Aufruf auftritt.Die Signatur
void f(std::unique_ptr<int> u);drückt bereits aus, dass hier Besitz zur Funktion übertragen wird -- einfach durch die Semantik von
unique_ptr, der nur gemoved werden kann. Pass By Value impliziert hier also Besitzübertragung. Diese Signatur verwirrt wahrscheinlich auch weniger.
-
@otze: Das meintest du! In Ordnung, tut mir Leid. Ja, ich habe falsche Annahmen über die Anforderungen gestellt. Tatsächlich sollte ich solche Pauschalaussagen einfach unterlassen.

oder wenn du spezifisch optimieren willst, um Moves zu vermeiden
*Kopien
Hier wird auch die Falschheit meiner Aussage deutlich. Hätte man einen
shared_ptrverwendet, so könnte man bspw. auch einen anderenshared_ptrübergeben - es kann aber nie davon ausgegangen werden, dass der Ownership ganz an die Funktion übergeht. Beiunique_ptrist das, wie Nexus erklärt hat, impliziert.
-
Sone schrieb:
oder wenn du spezifisch optimieren willst, um Moves zu vermeiden
*Kopien
Nein, ich meinte schon Moves.
Mit RValue-Referenzen hast du bereits eine Referenz auf das Originalobjekt, daher ist der Move unnötig.
-
Nexus schrieb:
Sone schrieb:
oder wenn du spezifisch optimieren willst, um Moves zu vermeiden
*Kopien
Nein, ich meinte schon Moves.
Mit RValue-Referenzen hast du bereits eine Referenz auf das Originalobjekt, daher ist der Move unnötig.
Ach, du meinst mit Move statt dem Cast zu einer rvalue-Referenz durch
std::moveden Aufruf eines Move-Konstruktors. Klar, der kann natürlich auch Overhead verursachen.
-
Nexus schrieb:
Die Signatur
void f(std::unique_ptr<int> u);drückt bereits aus, dass hier Besitz zur Funktion übertragen wird -- einfach durch die Semantik von
unique_ptr, der nur gemoved werden kann. Pass By Value impliziert hier also Besitzübertragung. Diese Signatur verwirrt wahrscheinlich auch weniger.Gerade diese Signatur verwirrt mich extrem. Es war doch genau die Frage, wie man ein Objekt per Value über geben kann, dass nicht kopiert werden kann. Was für einen Sinn macht das?
-
TNA schrieb:
Es war doch genau die Frage, wie man ein Objekt per Value über geben kann, dass nicht kopiert werden kann. Was für einen Sinn macht das?
Das Verständnis "Pass By Value == Kopie" ist veraltet.
In C++11 kann Pass By Value den Aufruf eines Move-Konstruktors statt eines Kopierkonstruktors bedeuten. Daher macht es sehr wohl Sinn, nichtkopierbare Objekte als Wert zu übergeben.
Lies dir vielleicht die Artikelserie auf C++Next durch, da wird Move-Semantik gut erklärt.
-
Es war doch genau die Frage, wie man ein Objekt per Value über geben kann, dass nicht kopiert werden kann.
In dem man nicht den Kopierkonstruktor involviert, sondern den Move-Konstruktor. Wenn du ein rvalue-
unique_ptran die Funktion übergibst, dann wird ebenjener aufgerufen, und der alsdeleteddefinierte Kopierkonstruktor hat nix zu suchen.
-
Das ist alles verdammt kompliziert mit der move Semantik und rvalues. Ich dachte ich hätte das halbwegs verstanden aber es ist doch nicht so
Zumindest waren eure Erklärungen jetzt bei mehrfachen lesen ein bisschen erhellend.
-
Vielleicht hilft dir ja ein älterer Beitrag von mir.