operator new , operator new[]
|
Definiert im Header
<new>
|
||
|
Ersetzbare Allokationsfunktionen
|
||
|
void
*
operator new
(
std::
size_t
count
)
;
|
(1) | |
|
void
*
operator new
[
]
(
std::
size_t
count
)
;
|
(2) | |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(3) | (seit C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(4) | (seit C++17) |
|
Ersetzbare, nicht-werfende Allokationsfunktionen
|
||
|
void
*
operator new
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(5) | (noexcept seit C++11) |
|
void
*
operator new
[
]
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(6) | (noexcept seit C++11) |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(7) | (seit C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(8) | (seit C++17) |
|
Nicht-allozierende Platzierungs-Allokationsfunktionen
|
||
|
void
*
operator new
(
std::
size_t
count,
void
*
ptr
)
;
|
(9) |
(noexcept seit C++11)
(constexpr seit C++26) |
|
void
*
operator new
[
]
(
std::
size_t
count,
void
*
ptr
)
;
|
(10) |
(noexcept seit C++11)
(constexpr seit C++26) |
|
Benutzerdefinierte Platzierungs-Allokationsfunktionen
|
||
|
void
*
operator new
(
std::
size_t
count,
/* Argumente... */
)
;
|
(11) | |
|
void
*
operator new
[
]
(
std::
size_t
count,
/* Argumente... */
)
;
|
(12) | |
|
void
*
operator new
(
std::
size_t
count,
std:: align_val_t al, /* Argumente... */ ) ; |
(13) | (seit C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(14) | (seit C++17) |
|
Klassenspezifische Allokationsfunktionen
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count
)
;
|
(15) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count
)
;
|
(16) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(17) | (seit C++17) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(18) | (seit C++17) |
|
Klassenspezifische Platzierungs-Allokationsfunktionen
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count,
/* Argumente... */
)
;
|
(19) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
/* args... */
)
;
|
(20) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std:: align_val_t al, /* Argumente... */ ) ; |
(21) | (seit C++17) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* Argumente... */ ) ; |
(22) | (seit C++17) |
Versucht, die angeforderte Anzahl von Bytes zu allokieren, und die Allokationsanfrage kann fehlschlagen (selbst wenn die angeforderte Anzahl von Bytes null ist). Diese Allokationsfunktionen werden von new -Ausdrücken aufgerufen, um Speicher zu allokieren, in dem dann neue Objekte initialisiert würden. Sie können auch über die reguläre Funktionsaufruf-Syntax aufgerufen werden.
Überladungen ( 1-4 ) werden implizit in jeder Übersetzungseinheit deklariert, selbst wenn der <new> Header nicht eingebunden ist.
Siehe new expression für die Kriterien zur Auswahl der Überladung.
Inhaltsverzeichnis |
Parameter
| count | - | Anzahl der zu reservierenden Bytes |
| ptr | - | Zeiger auf einen Speicherbereich zur Initialisierung des Objekts |
| tag | - | Unterscheidungsmarkierung zur Auswahl nicht-werfender Überladungen |
| al | - | Zu verwendende Ausrichtung, ungültiger Wert führt zu undefiniertem Verhalten |
Rückgabewert
Exceptions
Globale Ersetzungen
Overloads ( 1-8 ) sind austauschbar . Die Effekte der Standardversionen sind:
- Wenn der Versuch erfolgreich ist, gibt er einen Zeiger auf den allokierten Speicher zurück.
- Andernfalls, falls derzeit kein new-handler installiert ist, wird std::bad_alloc geworfen.
-
Andernfalls ruft er den aktuell installierten new-handler auf.
- Wenn der new-handler zurückkehrt, startet er einen weiteren Allokationsversuch.
- Andernfalls beendet er den aktuellen Aufruf.
- Falls der Aufruf normal zurückkehrt, gibt das Ergebnis dieses Aufrufs zurück.
- Andernfalls gibt einen Nullzeiger zurück.
|
Auf Freestanding-Implementierungen ist es implementierungsdefiniert, ob die Standardversionen von ( 1-8 ) die oben geforderten Verhaltensweisen erfüllen. Es wird Freestanding-Implementierungen empfohlen, dass wenn eine dieser Standardversionen den Anforderungen einer Hosted-Implementierung entspricht, alle dies tun sollten. |
(since C++26) |
Globale
operator
-
new
/
delete
-Ersetzung:
#include <cstdio> #include <cstdlib> #include <new> // no inline, required by [replacement.functions]/3 void* operator new(std::size_t sz) { std::printf("1) new(size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } // no inline, required by [replacement.functions]/3 void* operator new[](std::size_t sz) { std::printf("2) new[](size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } void operator delete(void* ptr) noexcept { std::puts("3) delete(void*)"); std::free(ptr); } void operator delete(void* ptr, std::size_t size) noexcept { std::printf("4) delete(void*, size_t), size = %zu\n", size); std::free(ptr); } void operator delete[](void* ptr) noexcept { std::puts("5) delete[](void* ptr)"); std::free(ptr); } void operator delete[](void* ptr, std::size_t size) noexcept { std::printf("6) delete[](void*, size_t), size = %zu\n", size); std::free(ptr); } int main() { int* p1 = new int; delete p1; int* p2 = new int[10]; // guaranteed to call the replacement in C++11 delete[] p2; }
Mögliche Ausgabe:
// Compiled with GCC-5 in C++17 mode to obtain the following: 1) op new(size_t), size = 4 4) op delete(void*, size_t), size = 4 2) op new[](size_t), size = 40 5) op delete[](void* ptr)
Überladungen von
operator new
und
operator new[]
mit zusätzlichen benutzerdefinierten Parametern ("Placement-Formen", Versionen
(
11-14
)
) können wie üblich im globalen Gültigkeitsbereich deklariert werden und werden durch die entsprechenden
Placement-Formen
von
new
-Ausdrücken aufgerufen.
Die nicht-allozierenden Platzierungsformen des
operator new
(
9,10
)
der Standardbibliothek können nicht ersetzt werden und können nur angepasst werden, wenn der Platzierungs-
new
-Ausdruck nicht die
::
new
-Syntax verwendet hat, indem ein klassen-spezifischer Platzierungs-
new
(
19,20
)
mit passender Signatur bereitgestellt wird:
void
*
T
::
operator
new
(
std::
size_t
,
void
*
)
oder
void
*
T
::
operator
new
[
]
(
std::
size_t
,
void
*
)
.
|
Die Platzierungsform void * operator new ( std:: size_t , std:: size_t ) ist nicht erlaubt, da die passende Signatur der Freigabefunktion, void operator delete ( void * , std:: size_t ) , eine gewöhnliche (nicht-Platzierungs-) Freigabefunktion ist. |
(seit C++14) |
Klassenspezifische Überladungen
Sowohl Einzelobjekt- als auch Array-Allokierungsfunktionen können als öffentliche statische Memberfunktionen einer Klasse definiert werden (Versionen ( 15-18 ) ). Falls definiert, werden diese Allokierungsfunktionen durch new -Ausdrücke aufgerufen, um Speicher für Einzelobjekte und Arrays dieser Klasse zu allokieren, es sei denn, der new -Ausdruck verwendete die Form :: new , welche die klassenbezogene Suche umgeht. Das Schlüsselwort static ist für diese Funktionen optional: Unabhängig davon, ob es verwendet wird oder nicht, ist die Allokierungsfunktion eine statische Memberfunktion.
Der new -Ausdruck sucht zunächst im Klassenbereich nach dem Namen der entsprechenden Allokationsfunktion und danach im globalen Bereich. Beachten Sie, dass gemäß den Namenssucheregeln alle im Klassenbereich deklarierten Allokationsfunktionen alle globalen Allokationsfunktionen für die new -Ausdrücke verbergen, die versuchen, Objekte dieser Klasse zu allokieren.
|
Wenn Objekte und Arrays von Objekten mit einer Ausrichtung, die __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, allokiert werden, wird die Überladungsauflösung zweimal durchgeführt: zuerst für ausrichtungsbewusste Funktionssignaturen, dann für ausrichtungsunbewusste Funktionssignaturen. Dies bedeutet, dass wenn eine Klasse mit erweiterter Ausrichtung eine ausrichtungsunbewusste klassenspezifische Allokationsfunktion besitzt, diese Funktion aufgerufen wird, nicht die globale ausrichtungsbewusste Allokationsfunktion. Dies ist beabsichtigt: Es wird erwartet, dass das Klassenmitglied am besten weiß, wie mit dieser Klasse umzugehen ist. |
(since C++17) |
|
Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überlagerungsauflösung zweimal durchgeführt: zuerst für ausrichtungsunabhängige Funktionssignaturen, dann für ausrichtungsabhängige Funktionssignaturen. |
(since C++20) |
#include <cstddef> #include <iostream> // class-specific allocation functions struct X { static void* operator new(std::size_t count) { std::cout << "custom new for size " << count << '\n'; return ::operator new(count); } static void* operator new[](std::size_t count) { std::cout << "custom new[] for size " << count << '\n'; return ::operator new[](count); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
Mögliche Ausgabe:
custom new for size 1 custom new[] for size 10
Überladungen von
operator new
und
operator new[]
mit zusätzlichen benutzerdefinierten Parametern ("Platzierungsformen") können auch als Klassenmember definiert werden
(
19-22
)
). Wenn der Platzierungs-
new
-Ausdruck mit der passenden Signatur nach der entsprechenden Allokationsfunktion sucht, beginnt er im Klassenbereich, bevor der globale Bereich untersucht wird, und wenn das klassen-spezifische Platzierungs-
new
bereitgestellt wird, wird es aufgerufen.
|
Wenn Objekte und Arrays von Objekten mit einer Ausrichtung, die __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, allokiert werden, wird die Überladungsauflösung für Placement-Formen genauso zweimal durchgeführt wie für reguläre Formen: zuerst für ausrichtungsbewusste Funktionssignaturen, dann für ausrichtungsunbewusste Funktionssignaturen. |
(since C++17) |
|
Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überlagerungsauflösung für Placement-Formen ebenso zweimal durchgeführt wie für reguläre Formen: zuerst für ausrichtungsunabhängige Funktionssignaturen, dann für ausrichtungsabhängige Funktionssignaturen. |
(since C++20) |
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error(""); } // custom placement new static void* operator new(std::size_t count, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(count); } // custom placement delete static void operator delete(void* ptr, bool b) { std::cout << "custom placement delete called, b = " << b << '\n'; ::operator delete(ptr); } }; int main() { try { [[maybe_unused]] X* p1 = new (true) X; } catch (const std::exception&) {} }
Ausgabe:
custom placement new called, b = 1 custom placement delete called, b = 1
Wenn der klassenbezogene
operator new
eine Template-Funktion ist, muss er den Rückgabetyp
void
*
haben, das erste Argument
std::size_t
, und er muss zwei oder mehr Parameter besitzen. Mit anderen Worten: Nur Placement-Formen können Templates sein.
Hinweise
Obwohl das nicht-allozierende Placement- new ( 9,10 ) nicht ersetzt werden kann, kann eine Funktion mit derselben Signatur wie oben beschrieben im Klassenbereich definiert werden. Zusätzlich sind globale Überladungen erlaubt, die wie Placement- new aussehen, aber einen Nicht-Void-Zeigertyp als zweiten Parameter nehmen. Daher muss Code, der sicherstellen möchte, dass das echte Placement- new aufgerufen wird (z.B. std::allocator::construct ), :: new verwenden und den Zeiger auch auf void * casten.
Wenn das Verhalten einer Freigabefunktion die Standardbeschränkungen nicht erfüllt, ist das Verhalten undefiniert.
|
Die folgenden Funktionen müssen thread-sicher sein:
Aufrufe dieser Funktionen, die eine bestimmte Speichereinheit allozieren oder deallozieren, erfolgen in einer einzigen Gesamtordnung, und jeder solche Deallokationsaufruf happens-before dem nächsten Allokationsaufruf (falls vorhanden) in dieser Ordnung. |
(seit C++11) |
Es ist nicht spezifiziert, ob Bibliotheksversionen von
operator new
Aufrufe an
std::malloc
oder
std::aligned_alloc
(seit C++17)
durchführen.
Zum Laden einer großen Datei ist Dateimapping über betriebssystemspezifische Funktionen, z.B.
mmap
unter POSIX oder
CreateFileMapping
(
A
/
W
) zusammen mit
MapViewOfFile
unter Windows, der Zuweisung eines Puffers für Dateilesen vorzuziehen.
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_lib_freestanding_operator_new
|
202306L
|
(C++26) | Freestanding-Unterstützung für ersetzbaren operator new [1] |
0
|
(C++26) | Keine Freestanding-Unterstützung | |
__cpp_lib_constexpr_new
|
202406L
|
(C++26) | constexpr Placement- new und new [ ] |
- ↑ Formal erweitert sich dieses Makro zu 202306L wenn alle Standardversionen der ersetzbaren globalen Allokationsfunktionen die Anforderungen einer gehosteten Implementierung erfüllen.
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 |
|---|---|---|---|
| CWG 521 | C++98 |
jede von
std::bad_alloc
abgeleitete Klasse konnte geworfen werden,
selbst wenn die std::bad_alloc Basis mehrdeutig oder unzugänglich war |
die geworfene Ausnahme sollte
einem Handler vom Typ std::bad_alloc entsprechen |
| LWG 9 | C++98 |
mehrere Aufrufe zur Allokation von null
Bytes könnten denselben Zeiger liefern |
nur erlaubt, wenn alle zuvor
gelieferten Zeiger an Deallokationsfunktionen übergeben wurden |
| LWG 206 | C++98 |
das Ersetzen der ersetzbaren Allokationsfunktionen
beeinflusste nicht das Standardverhalten der entsprechenden ersetzbaren nicht-werfenden Allokationsfunktionen |
das Standardverhalten
ändert sich entsprechend |
| LWG 404 | C++98 |
Ersetzungen der ersetzbaren Allokations-
funktionen könnten als inline deklariert werden |
verboten, keine Diagnose erforderlich |
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 17.7 Dynamische Speicherverwaltung [support.dynamic]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 17.6 Dynamische Speicherverwaltung [support.dynamic]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 21.6 Dynamische Speicherverwaltung [support.dynamic]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 18.6 Dynamische Speicherverwaltung [support.dynamic]
- C++11-Standard (ISO/IEC 14882:2011):
-
- 18.6 Dynamische Speicherverwaltung [support.dynamic]
- C++03-Standard (ISO/IEC 14882:2003):
-
- 18.4 Dynamische Speicherverwaltung [lib.support.dynamic]
- C++98-Standard (ISO/IEC 14882:1998):
-
- 18.4 Dynamische Speicherverwaltung [lib.support.dynamic]
Siehe auch
|
[static]
(C++23)
|
weist Speicher unter Verwendung von
Allocator
zu
(öffentliche statische Elementfunktion von
std::generator<Ref,V,Allocator>::promise_type
)
|
|
Freigabefunktionen
(Funktion) |
|
|
(C++11)
|
ermittelt den aktuellen new-Handler
(Funktion) |
|
registriert einen new-Handler
(Funktion) |
|
|
(deprecated in C++17)
(removed in C++20)
|
reserviert nicht initialisierten Speicher
(Funktionstemplate) |
|
weist Speicher zu
(Funktion) |
|
|
(C++17)
|
weist ausgerichteten Speicher zu
(Funktion) |