std::make_shared, std::make_shared_for_overwrite
| Definiert in Header <memory> |
||
| template< class T, class... Args > shared_ptr<T> make_shared( Args&&... args ); |
(1) | (seit C++11) |
template< class T > shared_ptr<T> make_shared( std::size_t N ); |
(2) | (seit C++20) |
| template< class T > shared_ptr<T> make_shared(); |
(3) | (seit C++20) |
| template< class T > shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u ); |
(4) | (seit C++20) |
| template< class T > shared_ptr<T> make_shared( const std::remove_extent_t<T>& u ); |
(5) | (seit C++20) |
template< class T > shared_ptr<T> make_shared_for_overwrite(); |
(6) | (seit C++20) |
| template< class T > shared_ptr<T> make_shared_for_overwrite( std::size_t N ); |
(7) | (seit C++20) |
Weist Speicher für ein Objekt zu und initialisiert das Objekt mit den übergebenen Argumenten. Gibt ein std::shared_ptr-Objekt zurück, das das neu erstellte Objekt verwaltet.
T und wird konstruiert, als ob durch ::new (pv) T(std::forward<Args>(args)...), wobei pv ein void* Zeiger auf Speicher ist, der ausreicht, um ein Objekt vom Typ T zu speichern. Wenn das Objekt zerstört werden soll, wird es zerstört, als ob durch pt->~T(), wobei pt ein Zeiger auf dieses Objekt vom Typ T ist.|
Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn |
(seit C++20) |
T ein unbegrenzter Array-Typ ist.T. Jedes Element hat einen Standardinitialisierungswert.T ein begrenzter Array-Typ ist.T ein unbegrenzter Array-Typ ist.T. Jedes Element hat den Initialisierungswert u.T ein begrenzter Array-Typ ist.T.- Wenn
Tkein Array-Typ ist, wird das Objekt konstruiert, als ob durch ::new (pv) T, wobei pv ein void* Zeiger auf Speicher ist, der ausreicht, um ein Objekt vom TypTzu speichern. Wenn das Objekt zerstört werden soll, wird es zerstört, als ob durch pt->~T(), wobei pt ein Zeiger auf dieses Objekt vom TypTist. - Wenn
Tein begrenzter Array-Typ ist, ist der Initialisierungswert für jedes Element nicht spezifiziert.
T kein Array-Typ oder ein begrenzter Array-Typ ist.T ein unbegrenzter Array-Typ ist.
Initialisieren und Zerstören von Array-ElementenArray-Elemente vom Typ
2,3) ::new (pv) U()
4,5) ::new (pv) U(u)
6,7) ::new (pv) U
Wenn die Lebensdauer des vom zurückgegebenen std::shared_ptr verwalteten Objekts endet, oder wenn die Initialisierung eines Array-Elements eine Ausnahme auslöst, werden die initialisierten Elemente in umgekehrter Reihenfolge ihrer ursprünglichen Konstruktion zerstört. Für jedes zu zerstörende Array-Element vom Nicht-Array-Typ |
(seit C++20) |
[edit] Parameter
| args | - | Liste der Argumente, mit denen ein Objekt vom Typ T konstruiert werden soll |
| N | - | Array-Größe, die verwendet werden soll |
| u | - | der Initialisierungswert zur Initialisierung jedes Elements des Arrays |
[edit] Rückgabewert
std::shared_ptr auf ein Objekt vom Typ T oder std::remove_extent_t<T>[N], wenn T ein unbegrenzter Array-Typ ist(seit C++20).
Für den zurückgegebenen std::shared_ptr r gibt r.get() einen Nicht-Null-Zeiger zurück und r.use_count() gibt 1 zurück.
[edit] Ausnahmen
Kann std::bad_alloc oder jede Ausnahme auslösen, die vom Konstruktor von T ausgelöst wird. Wenn eine Ausnahme ausgelöst wird, haben die Funktionen keine Auswirkungen. Wenn während der Konstruktion des Arrays eine Ausnahme ausgelöst wird, werden bereits initialisierte Elemente in umgekehrter Reihenfolge zerstört.(seit C++20)
[edit] Hinweise
Diese Funktionen weisen typischerweise mehr Speicher zu als sizeof(T), um interne Verwaltungsstrukturen wie Referenzzähler zu ermöglichen.
Diese Funktionen können als Alternative zu std::shared_ptr<T>(new T(args...)) verwendet werden. Die Kompromisse sind
- std::shared_ptr<T>(new T(args...)) führt mindestens zwei Zuweisungen durch (eine für das Objekt
Tund eine für den Steuerblock des Shared Pointers), während std::make_shared<T> typischerweise nur eine Zuweisung durchführt (der Standard empfiehlt dies, schreibt es aber nicht vor; alle bekannten Implementierungen tun dies). - Wenn sich ein std::weak_ptr auf den von
std::make_sharederstellten Steuerblock bezieht, nachdem die Lebensdauer aller gemeinsamen Besitzer beendet ist, bleibt der vonTbelegte Speicher erhalten, bis auch alle schwachen Besitzer zerstört sind, was unerwünscht sein kann, wenn sizeof(T) groß ist. - std::shared_ptr<T>(new T(args...)) kann einen nicht-öffentlichen Konstruktor von
Taufrufen, wenn er in einem Kontext ausgeführt wird, in dem er zugänglich ist, währendstd::make_sharedöffentlichen Zugriff auf den ausgewählten Konstruktor benötigt. - Im Gegensatz zu den std::shared_ptr-Konstruktoren erlaubt
std::make_sharedkeinen benutzerdefinierten Deleter. -
std::make_sharedverwendet ::new, daher wird es, wenn durch eine klassenspezifische operator new ein spezielles Verhalten eingerichtet wurde, von std::shared_ptr<T>(new T(args...)) abweichen.
|
(bis C++20) |
|
(bis C++17) |
Ein Konstruktor, der shared_from_this ermöglicht mit einem Zeiger ptr vom Typ U*, bedeutet, dass er feststellt, ob U eine eindeutige und zugängliche(seit C++17) Basisklasse hat, die eine Spezialisierung von std::enable_shared_from_this ist, und wenn ja, evaluiert der Konstruktor if (ptr != nullptr && ptr->weak_this .expired())
ptr->weak_this = std::shared_ptr<std::remove_cv_t<U>>
(*this, const_cast<std::remove_cv_t<U>*>(ptr)); .
Die Zuweisung an weak_this ist nicht atomar und steht in Konflikt mit jedem potenziell gleichzeitigen Zugriff auf dasselbe Objekt. Dies stellt sicher, dass zukünftige Aufrufe von shared_from_this() den durch diesen Rohzeiger-Konstruktor erstellten gemeinsamen Besitz mit dem std::shared_ptr teilen würden.
Der Test ptr->weak_this .expired() im obigen Code stellt sicher, dass weak_this nicht neu zugewiesen wird, wenn er bereits einen Besitzer anzeigt. Dieser Test ist ab C++17 erforderlich.
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_shared_ptr_arrays |
201707L |
(C++20) | Array-Unterstützung für std::make_shared; Überladungen (2-5) |
__cpp_lib_smart_ptr_for_overwrite |
202002L |
(C++20) | Erstellung von Smart Pointern mit Standardinitialisierung (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite); Überladungen (6,7) |
[edit] Beispiel
#include <iostream> #include <memory> #include <type_traits> #include <vector> struct C { // constructors needed (until C++20) C(int i) : i(i) {} C(int i, float f) : i(i), f(f) {} int i; float f{}; }; int main() { // using “auto” for the type of “sp1” auto sp1 = std::make_shared<C>(1); // overload (1) static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>); std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n"; // being explicit with the type of “sp2” std::shared_ptr<C> sp2 = std::make_shared<C>(2, 3.0f); // overload (1) static_assert(std::is_same_v<decltype(sp2), std::shared_ptr<C>>); static_assert(std::is_same_v<decltype(sp1), decltype(sp2)>); std::cout << "sp2->{ i:" << sp2->i << ", f:" << sp2->f << " }\n"; // shared_ptr to a value-initialized float[64]; overload (2): std::shared_ptr<float[]> sp3 = std::make_shared<float[]>(64); // shared_ptr to a value-initialized long[5][3][4]; overload (2): std::shared_ptr<long[][3][4]> sp4 = std::make_shared<long[][3][4]>(5); // shared_ptr to a value-initialized short[128]; overload (3): std::shared_ptr<short[128]> sp5 = std::make_shared<short[128]>(); // shared_ptr to a value-initialized int[7][6][5]; overload (3): std::shared_ptr<int[7][6][5]> sp6 = std::make_shared<int[7][6][5]>(); // shared_ptr to a double[256], where each element is 2.0; overload (4): std::shared_ptr<double[]> sp7 = std::make_shared<double[]>(256, 2.0); // shared_ptr to a double[7][2], where each double[2] // element is {3.0, 4.0}; overload (4): std::shared_ptr<double[][2]> sp8 = std::make_shared<double[][2]>(7, {3.0, 4.0}); // shared_ptr to a vector<int>[4], where each vector // has contents {5, 6}; overload (4): std::shared_ptr<std::vector<int>[]> sp9 = std::make_shared<std::vector<int>[]>(4, {5, 6}); // shared_ptr to a float[512], where each element is 1.0; overload (5): std::shared_ptr<float[512]> spA = std::make_shared<float[512]>(1.0); // shared_ptr to a double[6][2], where each double[2] element // is {1.0, 2.0}; overload (5): std::shared_ptr<double[6][2]> spB = std::make_shared<double[6][2]>({1.0, 2.0}); // shared_ptr to a vector<int>[4], where each vector // has contents {5, 6}; overload (5): std::shared_ptr<std::vector<int>[4]> spC = std::make_shared<std::vector<int>[4]>({5, 6}); }
Ausgabe
sp1->{ i:1, f:0 }
sp2->{ i:2, f:3 }[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 4024 | C++20 | war unklar, wie die instd::make_shared_for_overwrite konstruierten Objekte zerstört werden |
wurde klargestellt |
[edit] Siehe auch
erstellt einen neuen shared_ptr(public member function) | |
| erstellt einen geteilten Zeiger, der ein neues Objekt verwaltet, das mithilfe eines Allokators zugewiesen wurde (Funktionsschablone) | |
| (C++11) |
ermöglicht einem Objekt, einen auf sich selbst verweisenden shared_ptr zu erstellen(Klassen-Template) |
| (C++14)(C++20) |
Erstellt einen unique Pointer, der ein neues Objekt verwaltet (Funktionsschablone) |
| Allokationsfunktionen (Funktion) |