Namensräume
Varianten
Aktionen

operator new, operator new[]

Von cppreference.com
< cpp‎ | memory‎ | new
 
 
Dienstprogramm-Bibliotheken
Sprachunterstützung
Typunterstützung (Basistypen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programm-Dienstprogramme
Variadische Funktionen
Coroutine-Unterstützung (C++20)
Vertragsunterstützung (C++26)
Drei-Wege-Vergleich
(C++20)
(C++20)(C++20)(C++20)  
(C++20)(C++20)(C++20)

Allgemeine Hilfsmittel
Relationale Operatoren (in C++20 veraltet)
 
Speicherverwaltungsbibliothek
(nur Exposition*)
Algorithmen für uninitialisierten Speicher
(C++17)
(C++17)
(C++17)
Beschränkte uninitialisierte
Speicher-Algorithmen
C-Bibliothek

Allocatoren
Speicherressourcen
Unterstützung für Garbage Collection
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
(C++11)(bis C++23)
Uninitialisierter Speicher
Explizites Lebenszeitmanagement
 
 
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 Placement-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 Placement-Allokationsfunktionen
void* operator new  ( std::size_t count, /* args... */ );
(11)
void* operator new[]( std::size_t count, /* args... */ );
(12)
void* operator new  ( std::size_t count,
                      std::align_val_t al, /* args... */ );
(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 Placement-Allokationsfunktionen
void* T::operator new  ( std::size_t count, /* args... */ );
(19)
void* T::operator new[]( std::size_t count, /* args... */ );
(20)
void* T::operator new  ( std::size_t count,
                         std::align_val_t al, /* args... */ );
(21) (seit C++17)
void* T::operator new[]( std::size_t count,
                         std::align_val_t al, /* args... */ );
(22) (seit C++17)

Versuchen, die angeforderte Anzahl von Bytes zuzuweisen, wobei die Allokationsanforderung fehlschlagen kann (auch wenn die angeforderte Anzahl von Bytes null ist). Diese Allokationsfunktionen werden von new-Ausdrücken aufgerufen, um Speicher zuzuweisen, in dem dann ein neues Objekt initialisiert wird. Sie können auch mit normaler Funktionsaufrufsyntax aufgerufen werden.

1-8) Ersetzbare Allokationsfunktionen. Die Standardbibliothek stellt Standardimplementierungen für diese Funktionen bereit. Die Effekte der Standardimplementierungen finden Sie weiter unten.
9,10) Aufgerufen von den Standard- Placement-new-Ausdrücken. Führt keine Aktion aus und gibt ptr unverändert zurück.
Wenn diese Funktion über Placement-new aufgerufen wird und ptr ein Nullzeiger ist, ist das Verhalten undefiniert.
11-22) Benutzerdefinierte Allokationsfunktionen, die von new-Ausdrücken aufgerufen werden.

Überladungen (1-4) werden in jeder Translation Unit implizit deklariert, auch wenn der Header <new> nicht eingebunden ist.

Siehe new-Ausdruck für die Kriterien zur Auswahl einer Überladung.

Inhalt

[edit] Parameter

zählt - Anzahl der zuzuweisenden Bytes
ptr - Zeiger auf einen Speicherbereich, an dem das Objekt initialisiert werden soll
tag - Disambiguierungs-Tag zur Auswahl von Nicht-werfenden Überladungen
al - zu verwendende Ausrichtung; ein ungültiger Wert führt zu undefiniertem Verhalten

[edit] Rückgabewert

1-4) Wenn die Zuweisung erfolgreich ist, ein Nicht-Null-Zeiger p0, der auf einen passend ausgerichteten Speicher der Größe mindestens size zeigt und sich von jedem zuvor zurückgegebenen Wert p1 unterscheidet, es sei denn, dieser Wert p1 wurde anschließend einer ersetzbaren Deallokationsfunktion übergeben; schlägt die Zuweisung fehl, wird nicht zurückgegeben (eine Ausnahme wird ausgelöst, siehe unten).
5-8) Wie (1-4), gibt jedoch einen Nullzeiger zurück, wenn die Zuweisung fehlschlägt.
9,10) ptr
11-22) Wie (1-4), wenn die Funktion bei fehlgeschlagener Allokation nicht zurückkehrt, andernfalls wie (5-8).

[edit] Ausnahmen

1-4) Löst bei fehlgeschlagener Speicherzuweisung eine Ausnahme vom Typ aus, die zu einem Handler vom Typ std::bad_alloc passen würde.
11-22) Wie (1-4), wenn die Funktion bei fehlgeschlagener Allokation nicht zurückkehrt, andernfalls wie (5-8).

[edit] Globale Ersetzungen

Die Überladungen (1-8) sind ersetzbar. Die Effekte der Standardversionen sind

1) Versucht, den angeforderten Speicher zuzuweisen. Ob der Versuch einen Aufruf von std::malloc oder std::aligned_alloc beinhaltet, ist nicht spezifiziert.
  • Wenn der Versuch erfolgreich ist, wird ein Zeiger auf den zugewiesenen Speicher zurückgegeben.
  • Andernfalls, wenn derzeit kein new-Handler installiert ist, wird std::bad_alloc ausgelöst.
  • Andernfalls wird der aktuell installierte new-Handler aufgerufen.
    • Wenn der new-Handler zurückkehrt, wird ein weiterer Zuweisungsversuch gestartet.
    • Andernfalls wird der aktuelle Aufruf beendet.
2) Gibt zurück operator new(count).
3) Wie (1).
4) Gibt zurück operator new(count, al).
5-8) Ruft (1-4) entsprechend mit denselben Argumenten auf, außer tag.
  • Wenn der Aufruf normal zurückkehrt, wird das Ergebnis dieses Aufrufs zurückgegeben.
  • Andernfalls wird ein Nullzeiger zurückgegeben.

In freestanding Implementierungen ist es implementierungsdefiniert, ob die Standardversionen von (1-8) die oben geforderten Verhaltensweisen erfüllen. Freestanding Implementierungen wird empfohlen, dass, wenn eine dieser Standardversionen die Anforderungen einer gehosteten Implementierung erfüllt, alle dies tun sollten.

(seit 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 Geltungsbereich deklariert werden und werden von den passenden Placement-Formen von new-Ausdrücken aufgerufen.

Die nicht-allozierenden Standard-Placement-Formen von operator new (9,10) können nicht ersetzt werden und können nur dann angepasst werden, wenn der Placement-new-Ausdruck nicht die Syntax ::new verwendet hat, indem eine klassenspezifische Placement-new-Funktion (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 Placement-Form void* operator new(std::size_t, std::size_t) ist nicht erlaubt, da die passende Signatur der Deallokationsfunktion, void operator delete(void*, std::size_t), eine übliche (keine Placement-)Deallokationsfunktion ist.

(seit C++14)

[edit] Klassenspezifische Überladungen

Sowohl Allokationsfunktionen für einzelne Objekte als auch für Arrays können als öffentliche statische Memberfunktionen einer Klasse definiert werden (Versionen (15-18)). Wenn sie definiert sind, werden diese Allokationsfunktionen von new-Ausdrücken aufgerufen, um Speicher für einzelne Objekte und Arrays dieser Klasse zuzuweisen, es sei denn, der new-Ausdruck verwendet die Form ::new, die die Suche im Klassengeltungsbereich umgeht. Das Schlüsselwort static ist für diese Funktionen optional: Unabhängig davon, ob es verwendet wird oder nicht, ist die Allokationsfunktion eine statische Memberfunktion.

Der new-Ausdruck sucht zuerst im Klassengeltungsbereich nach dem Namen der passenden Allokationsfunktion und danach im globalen Geltungsbereich. Beachten Sie, dass gemäß den Namensauflösungsregeln jede im Klassengeltungsbereich deklarierte Allokationsfunktion alle globalen Allokationsfunktionen für die new-Ausdrücke, die versuchen, Objekte dieser Klasse zuzuweisen, ausblendet.

Beim Zuweisen von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, wird die Überladungsauflösung zweimal durchgeführt: zuerst für ausrichtungsabhängige Funktionssignaturen, dann für ausrichtungsunabhängige Funktionssignaturen. Das bedeutet, dass, wenn eine Klasse mit erweiterter Ausrichtung eine ausrichtungsunabhängige klassenspezifische Allokationsfunktion hat, diese Funktion aufgerufen wird und nicht die globale ausrichtungsabhängige Allokationsfunktion. Dies ist beabsichtigt: Der Klassenmember soll am besten wissen, wie er mit dieser Klasse umzugehen hat.

(seit C++17)

Beim Zuweisen von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überladungsauflösung zweimal durchgeführt: zuerst für ausrichtungsunabhängige Funktionssignaturen, dann für ausrichtungsabhängige Funktionssignaturen.

(seit 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 ("Placement-Formen") können ebenfalls als Klassenmitglieder definiert werden (19-22)). Wenn der Placement-new-Ausdruck mit der passenden Signatur nach der entsprechenden Allokationsfunktion sucht, beginnt er im Klassengeltungsbereich, bevor der globale Geltungsbereich untersucht wird, und wenn die klassenspezifische Placement-new-Funktion bereitgestellt wird, wird sie aufgerufen.

Beim Zuweisen von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, wird die Überladungsauflösung für Placement-Formen zweimal durchgeführt, genau wie für reguläre Formen: zuerst für ausrichtungsabhängige Funktionssignaturen, dann für ausrichtungsunabhängige Funktionssignaturen.

(seit C++17)

Beim Zuweisen von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überladungsauflösung für Placement-Formen zweimal durchgeführt, genau wie für reguläre Formen: zuerst für ausrichtungsunabhängige Funktionssignaturen, dann für ausrichtungsabhängige Funktionssignaturen.

(seit 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 die klassenbezogene operator new-Funktion eine Vorlagenfunktion ist, muss sie den Rückgabetyp void*, das erste Argument std::size_t haben und mindestens zwei Parameter aufweisen. Mit anderen Worten, nur Placement-Formen können Vorlagen sein.

[edit] Hinweise

Obwohl die nicht-allozierenden Placement-new-Funktionen (9,10) nicht ersetzt werden können, kann eine Funktion mit derselben Signatur wie oben beschrieben im Klassengeltungsbereich definiert werden. Darüber hinaus sind globale Überladungen, die wie Placement-new-Funktionen aussehen, aber einen Zeigertyp, der kein void* ist, als zweites Argument annehmen, zulässig. Daher muss Code, der sicherstellen möchte, dass die tatsächliche Placement-new-Funktion aufgerufen wird (z. B. std::allocator::construct), ::new verwenden und den Zeiger auch nach void* casten.

Wenn das Verhalten einer Deallokationsfunktion die Standardbeschränkungen nicht erfüllt, ist das Verhalten undefiniert.

Die folgenden Funktionen sind Thread-sicher erforderlich

Aufrufe dieser Funktionen, die eine bestimmte Speichereinheit zuweisen oder freigeben, erfolgen in einer einzigen Gesamtordnung, und jeder solche Freigabeaufruf happens-before die nächste Zuweisung (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) tätigen.

Zum Laden einer großen Datei ist die Dateizuordnung über betriebssystemspezifische Funktionen, z. B. mmap unter POSIX oder CreateFileMapping(A/W) zusammen mit MapViewOfFile unter Windows, der Allokation eines Puffers für das Dateilesen vorzuziehen.

Feature-Test-Makro Wert Std Feature
__cpp_lib_freestanding_operator_new 202306L (C++26) freestanding-Unterstützung für ersetzbares operator new[1]
0 (C++26) keine freestanding-Unterstützung
__cpp_lib_constexpr_new 202406L (C++26) constexpr Placement new und new[]
  1. Formell wird dieses Makro zu 202306L erweitert, wenn alle Standardversionen der ersetzbaren globalen Allokationsfunktionen die Anforderungen einer gehosteten Implementierung erfüllen.

[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
CWG 521 C++98 Jede von std::bad_alloc abgeleitete Klasse könnte ausgelöst werden,
auch wenn die std::bad_alloc Basis mehrdeutig oder unzugänglich ist
die ausgelöste Ausnahme sollte passen
zu einem Handler vom Typ std::bad_alloc
LWG 9 C++98 Mehrere Aufrufe zum Zuweisen von Null
Bytes könnten denselben Zeiger ergeben
nur erlaubt, wenn alle zuvor
ergebenen Zeiger
an Deallokationsfunktionen übergeben wurden
LWG 206 C++98 Das Ersetzen der ersetzbaren Allokationsfunktionen hat
nicht die Standardverhalten der entsprechenden
ersetzbaren Nicht-werfenden Allokationsfunktionen beeinflusst
Die Standardverhalten
ändern sich entsprechend
LWG 404 C++98 Ersetzungen der ersetzbaren Allokations
funktionen könnten inline deklariert werden
verboten, keine Diagnose erforderlich

[edit] 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]

[edit] Siehe auch

[static] (C++23)
alloziiert Speicher mittels Allocator
(public static member function of std::generator<Ref,V,Allocator>::promise_type) [edit]
Deallokationsfunktionen
(Funktion) [bearbeiten]
holt den aktuellen new handler
(Funktion) [bearbeiten]
registriert einen new handler
(Funktion) [bearbeiten]
(veraltet in C++17)(entfernt in C++20)
ermöglicht den Zugriff auf uninitialisierten Speicher
(Funktions-Template) [edit]
alloziert Speicher
(function) [edit]
alloziert ausgerichteten Speicher
(function) [edit]