Namespaces
Variants

operator new, operator new[]

Von de.cppreference.net
< cpp | memory | new
 
 
Dienstprogrammbibliothek
Sprachunterstützung
Typunterstützung (grundlegende Typen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programmdienstprogramme
Variadische Funktionen
Koroutinenunterstützung (C++20)
Vertragsunterstützung (C++26)
Dreiseitiger Vergleich
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Allgemeine Dienstprogramme
Relationale Operatoren (veraltet in C++20)
Ganzzahlvergleichsfunktionen
(C++20)(C++20)(C++20)    
(C++20)
Swap und Typoperationen
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Allgemeine Vokabeltypen
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
Speicherverwaltungsbibliothek
Allokatoren
Speicherressourcen
Nicht initialisierter Speicher (bis C++20*)
Garbage-Collector-Unterstützung (bis C++23)
 
 
Definiert in 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-allokierende 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, /* 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 Platzierungs-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)

Versucht, die angeforderte Anzahl von Bytes zu allozieren, und die Allokationsanforderung kann fehlschlagen (auch wenn die angeforderte Anzahl von Bytes null ist). Diese Allokationsfunktionen werden von new-Ausdrücken aufgerufen, um Speicher zu allozieren, 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; für die Wirkungen der Standardimplementierungen siehe unten.
9,10) Werden von den standardmäßigen Platzierungs-newNew-Ausdrücken aufgerufen. Führen keine Aktion aus und geben ptr unverändert zurück.
Wenn diese Funktion durch einen Platzierungs-New-Ausdruck aufgerufen wird und new ein Nullzeiger ist, ist das Verhalten undefiniert.ptr
11-22) Benutzerdefinierte Allokationsfunktionen, die von new-New-Ausdrücken

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

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

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

1-4) Wenn die Allokation erfolgreich ist, ein nicht-null Zeiger p0 der auf geeignet ausgerichteten Speicher einer Größe von mindestens size zeigt und sich von jedem zuvor zurückgegebenen Wert p1 unterscheidet, es sei denn dieser Wert p1 wurde anschließend an eine ersetzbare Deallokationsfunktion übergeben; wenn die Allokation fehlschlägt, wird nichts zurückgegeben (eine Exception wird geworfen, siehe unten).
5-8) Gleich wie ( 1-4 ) , gibt jedoch einen Nullzeiger zurück, wenn die Allokation fehlschlägt.
9,10) ptr
11-22) Gleich wie ( 1-4 ) wenn die Funktion bei Allokationsfehlern nicht zurückkehrt, andernfalls gleich wie ( 5-8 ) .

Exceptions

1-4) Wirft eine Ausnahme eines Typs, der einem Handler vom Typ std::bad_alloc bei Speicherallokierungsfehlern entsprechen würde.
11-22) Gleich wie ( 1-4 ) wenn die Funktion bei Allokierungsfehlern nicht zurückkehrt, andernfalls gleich wie ( 5-8 ) .

Globale Ersetzungen

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

1) Versucht, den angeforderten Speicher zu belegen. Ob der Versuch einen Aufruf von std::malloc oder std::aligned_alloc beinhaltet, ist nicht spezifiziert.
  • Wenn der Versuch erfolgreich ist, gibt es einen Zeiger auf den belegten Speicher zurück. Der Speicher ist an der fundamentalen Ausrichtung ausgerichtet(bis C++17)Der Speicher ist an __STDCPP_DEFAULT_NEW_ALIGNMENT__(seit C++17) ausgerichtet.
  • Andernfalls, wenn derzeit kein New-Handler installiert ist, wird std::bad_alloc geworfen.
  • Andernfalls wird der aktuell installierte New-Handler aufgerufen.
    • Wenn der New-Handler zurückkehrt, wird ein weiterer Belegungsversuch gestartet.
    • Andernfalls wird die aktuelle Aufrufinstanz beendet.
2) Gibt operator new(count) zurück.
3) Wie (1), außer dass der zurückgegebene Speicher an al ausgerichtet ist.
4) Gibt operator new(count, al) zurück.
5-8) Ruf (1–4) jeweils mit denselben Argumenten auf, mit Ausnahme von tag.
  • Wenn der Aufruf normal zurückkehrt, wird das Ergebnis dieses Aufrufs zurückgegeben.
  • Andernfalls wird ein Nullzeiger zurückgegeben.

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

(seit C++26)

Globale operators 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 („Platzierungsformen“, Versionen (11-14)) können wie üblich im globalen Gültigkeitsbereich deklariert werden und werden von den passenden Platzierungsformen von new-Ausdrücken aufgerufen.

Die nicht-belegenden Platzierungsformen von 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, indem eine klassen-spezifische 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 übliche (keine Platzierungs-) Freigabefunktion ist.

(seit C++14)

Klassenspezifische Überladungen

Sowohl Einzelobjekt- als auch Array-Allokationsfunktionen können als öffentliche statische Memberfunktionen einer Klasse definiert werden (Versionen (15-18)). Falls definiert, werden diese Allokationsfunktionen von new-Ausdrücken aufgerufen, um Speicher für Einzelobjekte und Arrays dieser Klasse zu allozieren, es sei denn, der new-Ausdruck verwendet die Form ::new, die die Sichtbarkeit im Klassenbereich 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 den Namen der passenden Allokationsfunktion zuerst im Klassenbereich und danach im globalen Bereich. Beachten Sie, dass gemäß den Namenssuchregeln alle im Klassenbereich deklarierten Allokationsfunktionen alle globalen Allokationsfunktionen für die new-Ausdrücke verdecken, die versuchen, Objekte dieser Klasse zu allozieren.

Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, wird die Überladungsauflösung zweimal durchgeführt: zuerst für ausrichtungsbewusste Funktionssignaturen, dann für ausrichtungsunbewusste Funktionssignaturen. Dies bedeutet, dass wenn eine Klasse mit neuer erweiterter Ausrichtung eine ausrichtungsunbewusste klassenspezifische Allokationsfunktion hat, diese Funktion aufgerufen wird, nicht die globale ausrichtungsbewusste Allokationsfunktion. Dies ist beabsichtigt: Das Klassenmitglied soll am besten wissen, wie diese Klasse zu behandeln ist.

(seit C++17)

Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überladungsauflösung zweimal durchgeführt: zuerst für ausrichtungsunbewusste Funktionssignaturen, dann für ausrichtungsbewusste 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 ("Platzierungsformen") können ebenfalls als Klassenmitglieder definiert werden (19-22)). Wenn der Platzierungs-new-Ausdruck mit der passenden Signatur nach der entsprechenden Allokationsfunktion sucht, beginnt er im Klassenbereich, bevor er den globalen Bereich untersucht, und wenn die klassenspezifische Platzierungs-new bereitgestellt wird, wird sie aufgerufen.

Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ überschreitet, wird die Überladungsauflösung für Platzierungsformen zweimal durchgeführt, genau wie bei regulären Formen: zuerst für ausrichtungsbewusste Funktionssignaturen, dann für ausrichtungsunbewusste Funktionssignaturen.

(seit C++17)

Beim Allozieren von Objekten und Arrays von Objekten, deren Ausrichtung __STDCPP_DEFAULT_NEW_ALIGNMENT__ nicht überschreitet, wird die Überladungsauflösung für Platzierungsformen zweimal durchgeführt, genau wie bei regulären Formen: zuerst für ausrichtungsunbewusste Funktionssignaturen, dann für ausrichtungsbewusste 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 klassenweite operator new eine Vorlagenfunktion ist, muss sie den Rückgabetyp void*, das erste Argument std::size_t haben und zwei oder mehr Parameter besitzen. Mit anderen Worten, nur Platzierungsformen können Vorlagen 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 [ ]
  1. ↑ 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)
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)
weist ausgerichteten Speicher zu
(Funktion)