shared_ptr zu einem Array: sollte es verwendet werden?

Lesezeit: 6 Minuten

shared ptr zu einem Array sollte es verwendet werden
tschah06

Nur eine kleine Rückfrage bzgl shared_ptr.

Ist es eine gute Praxis zu verwenden shared_ptr auf ein Array zeigen? Zum Beispiel,

shared_ptr<int> sp(new int[10]);

Wenn nicht, warum nicht? Ein Grund, der mir bereits bekannt ist, ist, dass man die nicht erhöhen/verringern kann shared_ptr. Daher kann es nicht wie ein normaler Zeiger auf ein Array verwendet werden.

  • FWIT, Sie können auch nur die Verwendung in Erwägung ziehen std::vector. Sie müssen darauf achten, das Array mithilfe von Referenzen herumzureichen, 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, wenn Sie es jemals wollen.

    – Nicu Stiurca

    30. November 2012 um 11:57 Uhr

  • Wenn die Größe des Arrays zur Kompilierzeit bestimmt wird, können Sie auch die Verwendung von in Betracht ziehen std::array. es ist schon fast das gleiche wie ein rohes Array, aber mit der richtigen Semantik für die Verwendung in den meisten Bibliothekskomponenten. Vor allem Gegenstände dieser Art werden mit zerstört deletenicht delete[]. Und anders vectorspeichert es die Daten direkt im Objekt, sodass Sie keine zusätzliche Zuordnung erhalten.

    – Celtschk

    19. April 2015 um 13:23 Uhr

shared ptr zu einem Array sollte es verwendet werden
Prätorianer

Mit C++17, shared_ptr kann verwendet werden, um ein dynamisch zugewiesenes Array zu verwalten. Die shared_ptr Template-Argument muss in diesem Fall sein T[N] oder T[]. Sie dürfen also schreiben

shared_ptr<int[]> sp(new int[10]);

Von n4659, [util.smartptr.shared.const]

  template<class Y> explicit shared_ptr(Y* p);

Erfordert: Y muss ein vollständiger Typ sein. Der Ausdruck delete[] pwann T ist ein Array-Typ, oder delete pwann T ist kein Array-Typ, muss ein wohldefiniertes Verhalten haben und darf keine Ausnahmen auslösen.

Bemerkungen: Wann T ein Arraytyp ist, darf dieser Konstruktor nicht an der Überladungsauflösung teilnehmen, es sei denn, der Ausdruck delete[] p ist wohlgeformt und entweder T ist U[N] und Y(*)[N] konvertierbar ist T*oder T ist
U[] und Y(*)[] konvertierbar ist T*. …

Um dies zu unterstützen, der Mitgliedstyp element_type ist jetzt definiert als

using element_type = remove_extent_t<T>;

Auf Array-Elemente kann über zugegriffen werden operator[]

  element_type& operator[](ptrdiff_t i) const;

Erfordert: get() != 0 && i >= 0. Wenn T ist U[N], i < N. …
Bemerkungen: Wann T kein Array-Typ ist, ist nicht angegeben, ob diese Member-Funktion deklariert ist. Wenn sie deklariert ist, ist ihr Rückgabetyp nicht angegeben, außer dass die Deklaration (obwohl nicht unbedingt die Definition) der Funktion wohlgeformt sein muss.


Vor C++17, shared_ptr könnten nicht verwendet werden, um dynamisch zugewiesene Arrays zu verwalten. Standardmäßig, shared_ptr werde anrufen delete auf das verwaltete Objekt, wenn keine Verweise mehr darauf verbleiben. Wenn Sie jedoch mithilfe von zuweisen new[] du musst anrufen delete[]und nicht deleteum die Ressource freizugeben.

Um richtig zu verwenden shared_ptr Bei 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>());

Jetzt shared_ptr wird richtig anrufen delete[] beim Zerstören des verwalteten Objekts.

Der benutzerdefinierte Löscher oben kann durch ersetzt werden

  • der std::default_delete partielle 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, es sei denn, Sie benötigen tatsächlich die gemeinsame Verwaltung des verwalteten Objekts, a unique_ptr ist für diese Aufgabe besser geeignet, da es teilweise auf Array-Typen spezialisiert ist.

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 bereitgestellt Bibliotheksgrundlagen Technische Spezifikationdie vergrößert shared_ptr damit es sofort einsatzbereit ist, wenn es ein Array von Objekten besitzt. Der aktuelle Entwurf der shared_ptr Änderungen, die für diesen TS vorgesehen sind, finden Sie in N4082. Diese Änderungen werden über die zugänglich sein std::experimental Namespace und enthalten in der <experimental/memory> Header. Einige der relevanten Änderungen zur Unterstützung shared_ptr für Arrays sind:

— Die Definition des Elementtyps element_type Änderungen

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;

– Nicht so wie unique_ptr partielle Spezialisierung für Arrays, beides shared_ptr<T[]> und shared_ptr<T[N]> gültig sein und beides ergibt sich delete[] für das verwaltete Array von Objekten aufgerufen wird.

 template<class Y> explicit shared_ptr(Y* p);

Erfordert: Y muss ein vollständiger Typ sein. Der Ausdruck delete[] pwann T ist ein Array-Typ, oder delete pwann T ist kein Array-Typ, muss wohlgeformt sein, ein gut definiertes Verhalten haben und keine Ausnahmen auslösen. Wann T ist U[N], Y(*)[N] soll umwandelbar sein T*; wann T ist U[], Y(*)[] soll umwandelbar sein T*; Andernfalls, Y* soll umwandelbar sein T*.

  • +1, Anmerkung: Es gibt auch Boost’s shared-array.

    – Jogojapan

    25. Oktober 2012 um 5:29 Uhr

  • @ tschah06 shared_ptr::get gibt einen Zeiger auf das verwaltete Objekt zurück. Sie können es also verwenden sp.get()[0] = 1; ... sp.get()[9] = 10;

    – Prätorianer

    25. Oktober 2012 um 5:52 Uhr


  • ALT: std::shared_ptr<int> sp( new int[10], std::default_delete<int[]>() ); siehe auch en.cppreference.com/w/cpp/memory/default_delete

    – johjp

    25. Oktober 2012 um 6:24 Uhr

  • @Jeremy Wenn die Größe zur Kompilierzeit bekannt ist, muss dafür keine Klasse geschrieben werden. std::shared_ptr<std::array<int,N>> sollte genug sein.

    – Prätorianer

    3. Oktober 2013 um 15:26 Uhr


  • Warum tut unique_ptr Holen Sie sich diese teilweise Spezialisierung aber shared_ptr nicht?

    – Adam

    30. Mai 2014 um 22:00 Uhr

1646941809 657 shared ptr zu einem Array sollte es verwendet werden
Timmm

Eine möglicherweise einfachere Alternative, die Sie möglicherweise verwenden können, ist shared_ptr<vector<int>>.

  • Ja, so ist es. Oder ein Vektor ist eine Obermenge eines Arrays – er hat die gleiche In-Memory-Darstellung (plus Metadaten), ist aber in der Größe veränderbar. Es gibt eigentlich keine Situationen, in denen Sie ein Array möchten, aber keinen Vektor verwenden können.

    – Timmm

    30. Dezember 2014 um 21:01 Uhr

  • Der Unterschied besteht hier darin, dass die Vektorgröße nicht mehr statisch ist und der Zugriff auf die Daten mit einem doppelten Umweg erfolgt. Wenn die Leistung nicht das kritische Problem ist, funktioniert dies, andernfalls kann das Teilen eines Arrays seinen eigenen Grund haben.

    – Emilio Garavaglia

    21. Oktober 2015 um 8:14 Uhr

  • Dann können Sie wahrscheinlich verwenden shared_ptr<array<int, 6>>.

    – Timmm

    21. Oktober 2015 um 9:33 Uhr

  • Der andere Unterschied ist, dass es leicht größer und langsamer als ein Raw-Array. Im Allgemeinen kein wirkliches Problem, aber tun wir nicht so, als wäre 1 == 1.1.

    – Andreas

    24. Dezember 2015 um 6:47 Uhr

  • Es gibt Situationen, in denen die Quelle der Daten im Array bedeutet, dass es unhandlich oder unnötig ist, sie in einen Vektor zu konvertieren; B. beim Abrufen eines Rahmens von einer Kamera. (Oder so verstehe ich es jedenfalls)

    – Narfanator

    30. Januar 2016 um 2:28 Uhr

988840cookie-checkshared_ptr zu einem Array: sollte es verwendet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy