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) |
Reserviert Speicher für ein Objekt und initialisiert das Objekt mit den bereitgestellten 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 für ein Objekt vom Typ
T
geeignet ist. 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 dann an der Überladungsauflösung teil, wenn
|
(seit C++20) |
T
ein unbounded array type ist.
T
. Jedes Element hat einen Standardinitialwert.
T
ein bounded array type ist.
T
ein unbounded array type ist.
T
. Jedes Element hat den Anfangswert
u
.
T
ein bounded array type 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 für ein Objekt vom TypTgeeignet ist. 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 Array-Typ mit fester Größe ist, ist der Anfangswert für jedes Element nicht spezifiziert.
T
kein Array-Typ ist oder ein Array-Typ mit fester Größe ist.
T
ein unbounded array type ist.
Initialisierung und Zerstörung von Array-Elementen
Array-Elemente vom Typ
2,3)
::
new
(
pv
)
U
(
)
4,5)
::
new
(
pv
)
U
(
u
)
6,7)
::
new
(
pv
)
U
Wenn die Lebensdauer des durch den 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) |
Parameter
| args | - |
Liste der Argumente, mit denen ein Objekt von
T
konstruiert wird
|
| N | - | zu verwendende Array-Größe |
| u | - | der Initialwert zur Initialisierung jedes Elements des Arrays |
Rückgabewert
std::shared_ptr
zu einem Objekt vom Typ
T
oder
std::
remove_extent_t
<
T
>
[
N
]
falls
T
ein unbegannter 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.
Exceptions
Kann
std::bad_alloc
oder jede Exception werfen, die vom Konstruktor von
T
geworfen wird. Wenn eine Exception geworfen wird, haben die Funktionen keine Wirkung.
Wenn eine Exception während der Konstruktion des Arrays geworfen wird, werden bereits initialisierte Elemente in umgekehrter Reihenfolge zerstört.
(seit C++20)
Hinweise
Diese Funktionen werden typischerweise mehr Speicher allokieren als sizeof ( T ) , um Platz für 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 Allokationen durch (eine für das Objekt
Tund eine für den Kontrollblock des Shared Pointers), während std :: make_shared < T > typischerweise nur eine Allokation durchführt (der Standard empfiehlt dies, verlangt es aber nicht; alle bekannten Implementierungen tun dies). -
Wenn irgendein
std::weak_ptr
auf den von
std::make_sharederstellten Kontrollblock verweist, nachdem die Lebensdauer aller Shared-Besitzer beendet ist, bleibt der vonTbelegte Speicher bestehen, bis auch alle Weak-Besitzer zerstört werden, 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 Zugang zum ausgewählten Konstruktor erfordert. -
Im Gegensatz zu den
std::shared_ptr
Konstruktoren erlaubt
std::make_sharedkeinen benutzerdefinierten Deleter. -
std::make_sharedverwendet :: new , daher unterscheidet es sich von std:: shared_ptr < T > ( new T ( args... ) ) , falls ein spezielles Verhalten mittels eines klassen-spezifischen operator new eingerichtet wurde.
|
(bis C++20) |
|
(bis C++17) |
Ein Konstruktor,
der
shared_from_this
mit einem Zeiger
ptr
vom Typ
U*
aktiviert, bedeutet, dass er bestimmt, ob
U
eine
eindeutige und zugängliche
(seit C++17)
Basisklasse besitzt, die eine Spezialisierung von
std::enable_shared_from_this
ist, und falls ja, wertet 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
)
)
;
aus.
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 Besitz mit dem
std::shared_ptr
teilen, der durch diesen Rohzeiger-Konstruktor erstellt wurde.
Der Test
ptr
-
>
weak_this
.
expired
(
)
im obigen Code stellt sicher, dass
weak_this
nicht neu zugewiesen wird, falls es bereits auf einen Besitzer verweist. Dieser Test ist ab C++17 erforderlich.
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_lib_shared_ptr_arrays
|
201707L
|
(C++20) |
Array-Unterstützung von
std::make_shared
; Überladungen
(
2-5
)
|
__cpp_lib_smart_ptr_for_overwrite
|
202002L
|
(C++20) |
Smart-Pointer-Erstellung mit Standardinitialisierung (
std::allocate_shared_for_overwrite
,
std::make_shared_for_overwrite
,
std::make_unique_for_overwrite
); Überladungen
(
6,7
)
|
Beispiel
#include <iostream> #include <memory> #include <type_traits> #include <vector> struct C { // Konstruktoren benötigt (bis C++20) C(int i) : i(i) {} C(int i, float f) : i(i), f(f) {} int i; float f{}; }; int main() { // Verwendung von "auto" für den Typ von "sp1" auto sp1 = std::make_shared<C>(1); // Überladung (1) static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>); std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n"; // explizite Angabe des Typs von "sp2" std::shared_ptr<C> sp2 = std::make_shared<C>(2, 3.0f); // Überladung (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 zu einem wertinitialisierten float[64]; Überladung (2): std::shared_ptr<float[]> sp3 = std::make_shared<float[]>(64); // shared_ptr zu einem wertinitialisierten long[5][3][4]; Überladung (2): std::shared_ptr<long[][3][4]> sp4 = std::make_shared<long[][3][4]>(5); // shared_ptr zu einem wertinitialisierten short[128]; Überladung (3): std::shared_ptr<short[128]> sp5 = std::make_shared<short[128]>(); // shared_ptr zu einem wertinitialisierten int[7][6][5]; Überladung (3): std::shared_ptr<int[7][6][5]> sp6 = std::make_shared<int[7][6][5]>(); // shared_ptr zu einem double[256], wobei jedes Element 2.0 ist; Überladung (4): std::shared_ptr<double[]> sp7 = std::make_shared<double[]>(256, 2.0); // shared_ptr zu einem double[7][2], wobei jeder double[2] // element ist {3.0, 4.0}; Überladung (4): std::shared_ptr<double[][2]> sp8 = std::make_shared<double[][2]>(7, {3.0, 4.0}); // shared_ptr zu einem vector<int>[4], wobei jeder vector // enthält Inhalte {5, 6}; Überladung (4): std::shared_ptr<std::vector<int>[]> sp9 = std::make_shared<std::vector<int>[]>(4, {5, 6}); // shared_ptr zu einem float[512], wobei jedes Element 1.0 ist; Überladung (5): std::shared_ptr<float[512]> spA = std::make_shared<float[512]>(1.0); // shared_ptr zu einem double[6][2], wobei jedes double[2]-Element // ist {1.0, 2.0}; Überladung (5): std::shared_ptr<double[6][2]> spB = std::make_shared<double[6][2]>({1.0, 2.0}); // shared_ptr zu einem vector<int>[4], wobei jeder vector // enthält Inhalte {5, 6}; Überladung (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 }
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| LWG 4024 | C++20 |
es war unklar, wie die in
std::make_shared_for_overwrite
konstruierten Objekte zerstört werden
|
klargestellt |
Siehe auch
konstruiert neuen
shared_ptr
(öffentliche Elementfunktion) |
|
|
erstellt einen Shared Pointer, der ein neues Objekt verwaltet, das mit einem Allokator alloziert wurde
(Funktionstemplate) |
|
|
(C++11)
|
ermöglicht einem Objekt, einen
shared_ptr
zu erstellen, der auf sich selbst verweist
(Klassentemplate) |
|
(C++14)
(C++20)
|
erstellt einen Unique Pointer, der ein neues Objekt verwaltet
(Funktionstemplate) |
|
Allokierungsfunktionen
(Funktion) |