Aufruf default-copy-Konstruktor von innen überlastet copy-Konstruktor
Schreiben brauche ich eine copy-Konstruktor deep kopiert den Inhalt von einer std::shared_ptr
. Es gibt jedoch eine Reihe von Variablen int a, b, c, d, e;
auch in der Klasse definiert. Gibt es eine Möglichkeit zum generieren der default-copy-Konstruktor-code (oder rufen Sie die Standard-copy-Konstruktor) in meinem neuen überlastet man.
Hier ist ein code-snippet mit einem Kommentar, hoffentlich klärt sich das Problem.
class Foo {
public:
Foo() {}
Foo(Foo const & other);
...
private:
int a, b, c, d, e;
std::shared_ptr<Bla> p;
};
Foo::Foo(Foo const & other) {
p.reset(new Bla(*other.p));
//Can I avoid having to write the default copy constructor code below
a = other.a;
b = other.b;
c = other.c;
d = other.d;
e = other.e;
}
- Warum brauchen Sie, um deep-copy ist ein gemeinsames Zeiger? Nicht seinen Sinn und Zweck auf eine gemeinsame Ressource? Wenn Sie haben einzigartige Eigentum, betrachten Sie mit einem
unique_ptr
. - Da jede Instanz von Foo braucht eine
shared_ptr
zu passieren um zu mehreren anderen Klassen. - Die "..." im obigen code stellt eine öffentliche Schnittstelle zum
p
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist die Frage, die code, da ich dies Schreibe:
Den oben genannten code ist wahrscheinlich falsch, weil
den default-Konstruktor Blätter
a
,b
,c
,d
unde
nicht initialisiert, undden code nicht übernehmen Zuordnung kopieren, und
den Ausdruck
new Bla(other.p)
erfordert, dassBla
hat einen Konstruktor nehmen einestd::shared_ptr<Bla>
, das ist extrem unwahrscheinlich.Mit
std::shared_ptr
dies würde zu C++11 code, um formal korrekte Sprache-klug. Ich glaube jedoch, dass es nur code, der verwendet, was verfügbar ist, mit Ihrem compiler. Und so glaube ich, dass die relevanten C++ - standard C++98, die mit der technischen Korrekturen von den C++03-änderung.Können Sie ganz einfach nutzen Sie die eingebauten (generiert) kopieren Initialisierung, auch in C++98, z.B.
Beachten Sie, dass dieser code nicht korrekt initialisieren, die in der Standard-Konstruktor, nicht übernehmen kopieren-Zuordnung (mit den swap-idiom) und erfordert keine spezielle smart-pointer-bewusst
Bla
Konstruktor, sondern benutzt nur die normalenBla
copy-Konstruktor zum kopieren.Bla
copy-Konstruktor soll nicht zu nehmenshared_ptr
. Guten Fang. Die Antwort steht noch und ist sehr gut, danke.Denke ich immer, dass Fragen wie diese sollte mindestens eine Antwort-Zitat aus dem standard für zukünftige Leser, so ist es hier.
§12.8.4 der standard besagt, dass:
Dies bedeutet, dass bei der definition einer Klasse hat explizit deklarieren Sie eine Kopie-Konstruktor ist nicht deklariert implizit. Also, wenn Sie erklären explizit, die implizit eine nicht vorhanden ist, so kann man es nicht nennen.
Wäre es einfacher zu schreiben, eine variation auf
shared_ptr
hat tief kopieren hinein gebaut. So, Sie nicht zu schreiben, ein copy-Konstruktor für Ihre main-Klasse; nur für diesen besonderendeep_copy_shared_ptr
geben. Ihredeep_copy_shared_ptr
hätte ein Kopie-Konstruktor, und es würde speichernshared_ptr
selbst. Es könnte sogar eine implizite Konvertierung zushared_ptr
, um es ein bisschen einfacher zu verwenden.Meines Wissens nach nicht, aber was Sie kann (und sollte) tun, ist die Verwendung einer Initialisierungsliste, wie dem auch sei:
Diese wird dich nicht retten aus dem schreiben, sondern es spart Ihnen vor möglichen Leistungseinbußen zuweisen (unneccessarily) default-konstruiert Mitglieder (wenn auch in diesem Fall könnte es in Ordnung sein) und die vielen Fallstricke dieser bringen könnte. Verwenden Sie immer Initialisierer-Listen in Konstruktoren, wenn möglich.
Und durch die Art und Weise, Kerrek Kommentar ist richtig. Warum brauchen Sie eine
shared_ptr
, wenn Sie eine Tiefe Kopie sowieso. In diesem Fall ist eineunique_ptr
besser geeignet sein könnten. Außerdem ist es Vorteileshared_ptr
ist nicht eine Allgemeine nicht-mehr-zu-denke-über-Freigabe-Lösung, und Sie sollten immer denken, wenn benötigen Sie einen smart-pointer und welche Art von smart-pointer ist am besten geeignet.Nicht möglich ist. Es ist entweder erstellen Sie eine benutzerdefinierte Kopie-Konstruktor (ganz auf eigene Faust) oder der compiler schreibt es für Sie.
Beachten Sie, dass wenn Sie schreiben, ein copy-Konstruktor, dann müssen Sie wahrscheinlich eine Kopie, Zuweisung und Destruktor als gut, weil das schreiben auf jeder dieser drei Ressource-management-Funktionen bedeutet, Sie sind Geschäftsführer einer Ressource. Mit der copy-and-swap-idiom, jedoch, Sie müssen nur schreiben die Kopie Logik einmal in den copy-Konstruktor, und Sie dann definieren Sie den Zuweisungsoperator in Bezug auf die Kopie-Konstruktor.
Abgesehen davon, ich bin mir nicht ganz sicher, warum man mit einem
shared_ptr<>
. Der Punkt, der eineshared_ptr<>
ist, um zu ermöglichen, dass mehrere Zeiger auf sicher zeigen auf das gleiche Objekt. Aber du bist nicht die Freigabe der pointee, Sie tief zu kopieren. Vielleicht sollten Sie ein raw-pointer statt, und frei in den Destruktor. Oder, noch besser, ersetzen Sie dieshared_ptr<>
mit einemclone_ptr
, und eliminieren dann die Kopie-Konstruktor, copy-Zuweisung und Destruktor insgesamt."..."
. Das ist nicht der Punkt der Frage. Der Punkt ist, dass es schön wäre, um nicht wieder schreiben, das kopieren von code fürint a, b, c, d, e;
könnte schon vom compiler erzeugt wird.Den Standard-Zuweisungs-operator hat den gleichen code wie die Standard-copy-Konstruktor. Zwar können Sie nicht die Standard-copy-Konstruktor von Ihrem überlast der gleiche code vorhanden ist, in der assignemnt so.
sollten bekommen, was Sie brauchen.
Edit: Nevermind, es ist in der Tat der gleiche code ist, und das explizite deklarieren der Kopie construtor verhindert generation 🙁
p = other.p
p ist eine shared_ptr-so greift es sich den Wert und erhöht den ref-count. Unter der Annahme von obigen code wurden vorgenommen, um die Arbeit, diep.reset
würde dann nur dekrementiert die Referenz-Anzahl für das ursprüngliche Objekt.