Ich habe eine Methode, die ein Objekt nach Wert zurückgibt. Die Methode stammt aus einer Bibliothek, über die ich keine Kontrolle habe. Für die weitere Bearbeitung des Objekts möchte ich weiterhin mit einem unique_ptr an diesem Objekt arbeiten. Hier ist ein Beispiel:
#include <iostream>
#include <memory>
class Bla {
public:
Bla() { std::cout << "Constructor!\n"; }
~Bla() { std::cout << "Destructor!\n"; }
};
Bla GetBla() {
Bla bla;
return std::move(bla);
}
int main() {
auto bla = std::make_unique<Bla>(GetBla());
}
Das Beispiel erzeugt die folgende Ausgabe:
Constructor!
Destructor!
Destructor!
Destructor!
Warum wird der Zerstörer von Bla hier dreimal gerufen? Ist die Art und Weise, wie ich den unique_prt erstelle, korrekt?
c++
unique-ptr
Tobi S.
quelle
quelle
std::move
bewegt nichts. Es wird nur von einem Typ zum anderen geworfen.std::move
onreturn
ist ein großer Fehler.Antworten:
Es gibt tatsächlich 3 Mal, dass eine Instanz von erstellt
Bla
wird.Kehre nicht durch Bewegung zurück.
bla
Kehre einfach zurück , in den meisten Fällen wird die Kopie entfernt.Beachten Sie, dass
make_unique<Bla>
immer eine neue Instanz erstellt wird. In diesem Fall wird die Kopie erstellt, da Sie eine andere Instanz übergeben.Ein Hinweis darauf, dass eine Kopierkonstruktion stattfindet, ist, dass Ihr Standardkonstruktor nur einmal aufgerufen wird, während der Destruktor dreimal aufgerufen wird. Dies liegt daran, dass in den beiden anderen Fällen der implizite Kopier- (oder Verschiebungs-) Konstruktor aufgerufen wird (
Bla::Bla(Bla const&)
).quelle
// 2nd construction (return by copy)
nicht richtig? Der zurückgegebene Wert wird verschiebungskonstruiert? Siehe dies (ich könnte mich irren): stackoverflow.com/a/60487169/5735010 .Der Compiler kann Sie sogar davor warnen
Ich bin nicht 100% sicher, aber ich denke, Sie erhalten die drei Desctructor-Anrufe von:
bla
vonGetBla()
GetBla()
nach seiner Verwendung instd::make_unique<Bla>(GetBla());
std::unique_ptr
Am einfachsten ist es,
std::make_uniqe
den Standardkonstruktor aufrufen zu lassenBla
:Ausgabe
quelle
Der richtige Weg zu erstellen
unique_ptr
:Ihr Code erstellt jedoch drei Instanzen von
Bla
:bla
inGetBla()
Funktion.GetBla()
.make_unique()
wird eine weitere Instanz erstellt.HINWEIS:
GetBla()
Rückgabewert eine Kopie des lokalen Objekts istbla
.GetBla()
kehrtmove
‚lokales Objekt ed, copy-elision unterdrückt wird.quelle
Um wirklich zu sehen, was hinter den Kulissen passiert, können Sie entweder einen Debugger verwenden oder einen Kopierkonstruktor definieren . Ich habe den Kopierkonstruktor in Ihren Code eingefügt. Probieren Sie den folgenden Code aus:
HINWEIS:
std::move
bewegt nichts. Es wirft nur auslvalue
Referenz zurvalue
Referenz umgewandelt, und Ihr zurückgegebenes Objekt könnte über einen Verschiebungskonstruktor erstellt worden sein (und die Kopierelision könnte unterdrückt werden), aber der Compiler hat denmove
Konstruktor nicht implizit deklariert , da Sie den Destruktor definiert haben (und ich habe einen Kopierkonstruktor hinzugefügt) in meinem Beispiel)Ausgänge:
Siehe meine Kommentare unten:
bla
ist in Funktion aufgebautGetBla()
über den Standardkonstruktor erstellt.GetBla()
Funktion wird aus dem in erstellten Objekt kopiert# 1
.bla
Objekt (in # 1 konstruiert) wird zerstört und sein Destruktor wird aufgerufen.std::make_unique<Bla>
Anrufenew
und dann den entsprechenden Konstruktor auf und wählt das auscopy
Konstruktor aus.quelle