util.smartptr.shared.const / 9 in C ++ 11:
Effekte: Erstellt ein shared_ptr-Objekt, dem das Objekt p und der Deleter d gehören. Der zweite und vierte Konstruktor verwenden eine Kopie von a, um Speicher für den internen Gebrauch zuzuweisen.
Der zweite und vierte Konstruktor haben diese Prototypen:
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
Im neuesten Entwurf entspricht util.smartptr.shared.const / 10 für unseren Zweck:
Effekte: Erstellt ein shared_ptr-Objekt, dem das Objekt p und der Deleter d gehören. Wenn T kein Array-Typ ist, aktivieren der erste und der zweite Konstruktor shared_from_this mit p. Der zweite und vierte Konstruktor verwenden eine Kopie von a, um Speicher für den internen Gebrauch zuzuweisen. Wenn eine Ausnahme ausgelöst wird, wird d (p) aufgerufen.
Der Allokator wird also verwendet, wenn er im zugewiesenen Speicher zugeordnet werden muss. Basierend auf dem aktuellen Standard und bei relevanten Fehlerberichten ist die Zuordnung nicht obligatorisch, sondern wird vom Ausschuss übernommen.
Obwohl die Schnittstelle von shared_ptr
eine Implementierung ermöglicht, bei der es nie einen Steuerblock und alle gibt shared_ptr
und weak_ptr
die in eine verknüpfte Liste aufgenommen werden, gibt es in der Praxis keine solche Implementierung. Darüber hinaus wurde der Wortlaut geändert, beispielsweise unter der Annahme, dass der Wortlaut use_count
geteilt wird.
Der Deleter muss sich nur konstruierbar bewegen. Somit ist es nicht möglich, mehrere Kopien in der zu haben shared_ptr
.
Man kann sich eine Implementierung vorstellen, die den Deleter in ein speziell entworfenes setzt shared_ptr
und ihn verschiebt, wenn das Special shared_ptr
gelöscht wird. Die Implementierung scheint zwar konform zu sein, ist aber auch seltsam, zumal möglicherweise ein Steuerblock für die Anzahl der Verwendungen erforderlich ist (es ist möglicherweise möglich, aber noch seltsamer, dasselbe mit der Anzahl der Verwendungen zu tun).
Relevante DRs, die ich gefunden habe: 545 , 575 , 2434 (die bestätigen, dass alle Implementierungen einen Steuerblock verwenden und zu implizieren scheinen, dass Multithreading-Einschränkungen dies etwas vorschreiben ), 2802 (was erfordert, dass sich der Deleter nur konstruierbar bewegt und somit die Implementierung verhindert, wo Der Deleter wird zwischen mehreren kopiert shared_ptr
.
a
) zum Freigeben dieses Speichers finden kann. Was bedeuten würde, dass diese Kopie von gespeichert wirda
. Es gibt keine Informationen darüber in [util.smartptr.shared.dest].Von std :: shared_ptr haben wir:
Und von std :: allocate_shared erhalten wir:
Es sieht also so aus, als ob std :: allocate_shared das
deleter
mit Ihrem zuordnen sollteAlloc
.n4810
BEARBEITEN : Und ab §20.11.3.6 Erstellung [util.smartptr.shared.create][Hervorhebung aller meiner]
Also der Standard sagt , dass
std::allocate_shared
sollte verwendet werdenAlloc
für den Steuerblock.quelle
n4810
und aktualisierte Antwort.make_shared
nicht um die Konstruktoren selbst. Trotzdem kann ich ein Mitglied für kleine Löscher verwenden.Ich glaube, das ist nicht spezifiziert.
Hier ist die Spezifikation der relevanten Konstruktoren: [util.smartptr.shared.const] / 10
Meine Interpretation lautet nun, dass die Implementierung, wenn sie Speicher für den internen Gebrauch benötigt, dies mithilfe von verwendet
a
. Dies bedeutet nicht, dass die Implementierung diesen Speicher verwenden muss, um alles zu platzieren. Angenommen, es gibt diese seltsame Implementierung:Verwendet diese Implementierung "eine Kopie von
a
, um Speicher für den internen Gebrauch zuzuweisen"? Ja tut es. Es wird niemals Speicher zugewiesen, außer durch Verwendunga
. Es gibt viele Probleme mit dieser naiven Implementierung, aber sagen wir, dass sie auf die Verwendung von Allokatoren umschaltet, außer im einfachsten Fall, in dem dershared_ptr
direkt aus einem Zeiger erstellt wird und niemals kopiert oder verschoben oder auf andere Weise referenziert wird und es keine anderen Komplikationen gibt. Der Punkt ist, nur weil wir uns eine gültige Implementierung nicht vorstellen können, beweist sie nicht, dass sie theoretisch nicht existieren kann. Ich sage nicht, dass eine solche Implementierung tatsächlich in der realen Welt zu finden ist, nur dass der Standard sie nicht aktiv zu verbieten scheint.quelle
shared_ptr
für kleine Typen reserviert Speicher auf dem Stapel. Und erfüllt damit nicht die Standardanforderungenstd::move(__d)
und greifen Sie zurück,allocate
wenn eine Kopie erforderlich ist.