Zu behandeln, wie eine Karte von shared_ptr mit move-Konstruktor richtig?
Überlegen, ich habe einen container std::map<int, std::shared_ptr<MyClass>>
und ich wollen füllen Sie es in externen Funktion und Vermeidung Bewältigungsstrategien von deren Inhalt. Also ich habe
typedef Container std::map<int, std::shared_ptr<MyClass>>
Container&& f(){
Container bar;
auto foo = std::shared_ptr<MyClass>(new MyClass());
bar.insert(std::make_pair(0,foo));
std::cout<<bar.at(1)->print_smth<<'\n'; //This works
return std::move(bar);
}
int main(){
Container baz(f());
std::cout<<bar.at(1)->print_smth<<'\n'; //This doesn't
//Container baz has element 1, but shared_ptr is invalidated, because it has 0 references.
}
Wenn ich mit herkömmlichen copy-Konstruktor funktioniert alles wie erwartet.
- Ein Rückgabewert ist bereits ein rvalue, und es wird wahrscheinlich keine Kopie gemacht durch RVO.
- Sie müssen nicht wieder einen Verweis auf eine lokale, automatische Objekt. Es ist ein Undefiniertes Verhalten für den Zugriff auf diese Referenz.
- in der Praxis ist mit einem modernen compiler eine Optimierung aktiviert, Sie sind richtig, aber ich trotzdem nicht verstehe was ich falsch mache.
bar
zerstört wird zurückkehren, wenn Sie vonf()
, so dass der Verweis auf die Rendite bezieht sich nicht auf ein gültiges Objekt. Daher Undefiniertes Verhalten. Und auch wenn die Optimierung aus irgendeinem Grund fehlschlagen, wird ein Wert zurückgegeben wird verschoben, nicht kopiert.- so, wie soll ich umgehen? Wenn ich einen container mit Zeigern evething funktionieren wird, aber ich werde Locker alle features von shared_ptr.
- Return-Wert. Es wird nicht kopiert werden.
- Return-Wert. Sie haben keine Wahl.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist weit zu kompliziert. Warum nicht einfach sagen:
Wenn Sie unbedingt gehen müssen, mit der helper-Funktion, müssen Sie ein Objekt zurückgeben, keine baumelnden Referenz. So etwas wie dieses:
Es ist schwer zu frönen, die nichts mehr Fußgänger als dieses, aber eine Letzte, nie-zu-sein-gebraucht-at-home-version:
return bar;
ermöglicht RVO, währendreturn std::move(bar);
eigentlich hemmt RVO.Das problem ist, dass Sie wieder einen Verweis von Ihrem
f()
. Eine rvalue-Referenz ist immer noch eine Referenz und gerade wie Sie würde nie wieder ein Verweis auf eine lokale von einer Funktion, die Sie können nicht tun, mit rvalue-Referenzen entweder.Die gute Nachricht ist, dass Sie nicht haben, um. Dank der return-Wert-Optimierung können Sie einfach eine
Container
ausf()
und es wird genau das tun, was Sie suchen.