Mit C ++ 17 , shared_ptrkann verwendet werden , um eine dynamisch zugewiesenen Array zu verwalten. Das shared_ptrVorlagenargument muss in diesem Fall T[N]oder sein T[]. Also kannst du schreiben
shared_ptr<int[]> sp(new int[10]);
Ab n4659 [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Benötigt: Y muss ein vollständiger Typ sein. Der Ausdruck delete[] p, wenn Tes sich um einen Array-Typ handelt oder delete pwenn Tes sich nicht um einen Array-Typ handelt, muss ein genau definiertes Verhalten aufweisen und keine Ausnahmen auslösen.
...
Anmerkungen: Wenn Tes sich um einen Array-Typ handelt, darf dieser Konstruktor nicht an der Überladungsauflösung teilnehmen, es sei denn, der Ausdruck delete[] pist wohlgeformt und Tist U[N]und Y(*)[N]ist konvertierbar in T*oder Tist
U[]und Y(*)[]ist konvertierbar in T*. ...
Um dies zu unterstützen, ist der Elementtyp element_typejetzt definiert als
using element_type = remove_extent_t<T>;
Auf Array-Elemente kann mit zugegriffen werden operator[]
element_type& operator[](ptrdiff_t i) const;
Benötigt : get() != 0 && i >= 0 . Wenn Tja U[N], i < N. ...
Anmerkungen: Wenn Tes sich nicht um einen Array-Typ handelt, ist nicht angegeben, ob diese Elementfunktion deklariert ist. Wenn es deklariert ist, ist nicht angegeben, um welchen Rückgabetyp es sich handelt, mit der Ausnahme, dass die Deklaration (obwohl nicht unbedingt die Definition) der Funktion wohlgeformt sein muss.
Vor dem C ++ 17 , shared_ptrkonnte nicht dynamisch zugewiesenen Arrays verwalten verwendet werden. Standardmäßig shared_ptrwird deletedas verwaltete Objekt aufgerufen , wenn keine Verweise mehr darauf vorhanden sind. Wenn Sie jedoch mit zuweisen, müssen new[]Sie die Ressource aufrufen delete[]und nicht delete, um sie freizugeben.
Zur korrekten Verwendung shared_ptrmit einem Array müssen Sie einen benutzerdefinierten Löscher angeben.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Erstellen Sie den shared_ptr wie folgt:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
shared_ptrWird jetzt korrekt aufgerufen, delete[]wenn das verwaltete Objekt zerstört wird.
Der oben angegebene benutzerdefinierte Löscher kann durch ersetzt werden
die std::default_deleteteilweise Spezialisierung für Array-Typen
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
ein Lambda-Ausdruck
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Außerdem unique_ptrist a für diese Aufgabe besser geeignet , es sei denn, Sie benötigen tatsächlich eine gemeinsame Verwaltung des verwalteten Objekts , da es eine teilweise Spezialisierung für Array-Typen aufweist.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Änderungen, die durch die C ++ - Erweiterungen für Bibliotheksgrundlagen eingeführt wurden
Eine weitere Alternative vor C ++ 17 zu den oben aufgeführten wurde von der Library Fundamentals Technical Specification bereitgestellt , die erweitert wurde shared_ptr, damit sie für den Fall, dass sie ein Array von Objekten besitzt, sofort einsatzbereit ist. Der aktuelle Entwurf der shared_ptrfür diesen TS geplanten Änderungen ist in N4082 zu finden . Auf diese Änderungen kann über den std::experimentalNamespace zugegriffen und in die <experimental/memory>Kopfzeile aufgenommen werden. Einige der relevanten Änderungen zur Unterstützung shared_ptrvon Arrays sind:
- Die Definition des Elementtyps element_typeändert sich
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Mitglied operator[]wird hinzugefügt
element_type& operator[](ptrdiff_t i) const noexcept;
- Im Gegensatz zur unique_ptrteilweisen Spezialisierung für Arrays sind beide shared_ptr<T[]>und shared_ptr<T[N]>gültig und führen dazu, delete[]dass das verwaltete Array von Objekten aufgerufen wird.
template<class Y> explicit shared_ptr(Y* p);
Benötigt : Ymuss ein vollständiger Typ sein. Der Ausdruck delete[] p, wenn Tes sich um einen Array-Typ handelt oder delete pwenn Tes sich nicht um einen Array-Typ handelt, muss wohlgeformt sein, ein genau definiertes Verhalten aufweisen und keine Ausnahmen auslösen. Wann Tist U[N], Y(*)[N]soll konvertierbar sein zu T*; wann Tist U[], Y(*)[]soll konvertierbar sein zu T*; Andernfalls Y*ist konvertierbar in T*.
std::vector. Sie müssen vorsichtig sein, um das Array mithilfe von Referenzen weiterzugeben, damit Sie keine Kopien davon erstellen. Die Syntax für den Zugriff auf Daten ist sauberer als shared_ptr, und die Größenänderung ist sehr, sehr einfach. Und Sie erhalten alle STL-Güte, falls Sie es jemals wollen.