new Operator (C++)

Versucht, ein Objekt oder array von Objekten eines angegebenen oder Platzhaltertyps zuzuweisen und zu initialisieren, und gibt einen entsprechend typisierten, nichtzero-Zeiger auf das Objekt (oder auf das anfängliche Objekt des Arrays) zurück.

Syntax

new-expression:
::optnewnew-placementoptnew-type-idnew-initializeropt
::optnewnew-placementopt(type-id)new-initializeropt

new-placement:
( expression-list )

new-type-id:
type-specifier-seqnew-declaratoropt

new-declarator:
ptr-operatornew-declaratoropt
noptr-new-declarator

noptr-new-declarator:
[expression]attribute-specifier-seqopt
noptr-new-declarator[constant-expression]attribute-specifier-seqopt

new-initializer:
(expression-listopt)
braced-init-list

Hinweise

Wenn dies nicht erfolgreich ist, new wird null zurückgegeben oder eine Ausnahme ausgelöst. Weitere Informationen finden Sie unter The new and delete Operators. Sie können dieses Standardverhalten ändern, indem Sie eine benutzerdefinierte Ausnahmebehandlungsroutine schreiben und die _set_new_handler Laufzeitbibliotheksfunktion mit dem Funktionsnamen als Argument aufrufen.

Informationen zum Erstellen eines Objekts im verwalteten Heap in C++/CLI und C++/CX finden Sie unter gcnew.

Hinweis

Microsoft C++-Komponentenerweiterungen (C++/CX) bieten Unterstützung für die new Schlüsselwort (keyword) zum Hinzufügen von Vtable-Sloteinträgen. Weitere Informationen finden Sie unter new (neuer Steckplatz in vtable)

Wenn new zum Zuordnen des Speichers für ein C++-Klassenobjekt verwendet wird, wird der Konstruktor des Objekts aufgerufen, nachdem der Speicher zugewiesen wurde.

Verwenden Sie den delete Operator, um den vom new Operator zugewiesenen Speicher zuzuordnen. Verwenden Sie den delete[] Operator, um ein vom new Operator zugeordnetes Array zu löschen.

Im folgenden Beispiel wird ein zweidimensionales Array der Größe dim durch 10 zugewiesen und dann freigegeben. Beim Zuweisen eines mehrdimensionalen Arrays müssen alle Dimensionen außer dem ersten konstanten Ausdruck sein, der zu positiven Werten ausgewertet wird. Die äußerst linke Arraydimension kann ein beliebiger Ausdruck sein, der zu einem positiven Wert ausgewertet wird. Beim Zuweisen eines Arrays mit dem new Operator kann die erste Dimension null sein. Der new Operator gibt einen eindeutigen Zeiger zurück.

char (*pchar)[10] = new char[dim][10];
delete [] pchar;

Die type-id Deklarationen können weder Deklarationen noch Enumerationsdeklarationen enthaltenconstvolatile. Der folgende Ausdruck ist unformiert:

volatile char *vch = new volatile char[20];

Der new Operator weist keine Verweistypen zu, da sie keine Objekte sind.

Der new Operator kann nicht zum Zuordnen einer Funktion verwendet werden, kann jedoch verwendet werden, um Zeigern funktionen zuzuweisen. Im folgenden Beispiel wird ein Array von sieben Zeigern auf Funktionen, die ganze Zahlen zurückgeben, zugewiesen und dann freigegeben.

int (**p) () = new (int (*[7]) ());
delete p;

Wenn Sie den Operator new ohne zusätzliche Argumente verwenden und mit dem /GX/EHa, oder /EHs der Option kompilieren, generiert der Compiler Code zum Aufrufen des Operatorsdelete, wenn der Konstruktor eine Ausnahme auslöst.

In der folgenden Liste werden die Grammatikelemente von new:

new-placement
Bietet eine Möglichkeit, zusätzliche Argumente zu übergeben, wenn Sie überladen new.

type-id
Gibt den typ an, der zugewiesen werden soll; es kann sich um einen integrierten oder benutzerdefinierten Typ sein. Eine komplizierte Typspezifikation können Sie in Klammern einschließen, um die Reihenfolge der Bindung zu erzwingen. Der Typ kann ein Platzhalter (auto) sein, dessen Typ vom Compiler bestimmt wird.

new-initializer
Stellt einen Wert für das initialisierte Objekt bereit. Initialisierer können für Arrays nicht angegeben werden. Der new Operator erstellt Arrays von Objekten nur, wenn die Klasse über einen Standardkonstruktor verfügt.

noptr-new-declarator
Gibt die Grenzen eines Arrays an. Beim Zuweisen eines mehrdimensionalen Arrays müssen alle Dimensionen außer dem ersten konstanten Ausdruck sein, der zu positiven Werten ausgewertet wird, die in konvertierbar sind std::size_t. Die äußerst linke Arraydimension kann ein beliebiger Ausdruck sein, der zu einem positiven Wert ausgewertet wird. Dies attribute-specifier-seq gilt für den zugeordneten Arraytyp.

Beispiel: Zuweisen und Freigeben eines Zeichenarrays

Im folgenden Codebeispiel werden ein Zeichenarray und ein Objekt der Klasse CName zugewiesen und dann wieder freigegeben.

// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>

class CName {
public:
   enum {
      sizeOfBuffer = 256
   };

   char m_szFirst[sizeOfBuffer];
   char m_szLast[sizeOfBuffer];

public:
   void SetName(char* pszFirst, char* pszLast) {
     strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
     strcpy_s(m_szLast, sizeOfBuffer, pszLast);
   }

};

int main() {
   // Allocate memory for the array
   char* pCharArray = new char[CName::sizeOfBuffer];
   strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");

   // Deallocate memory for the array
   delete [] pCharArray;
   pCharArray = NULL;

   // Allocate memory for the object
   CName* pName = new CName;
   pName->SetName("Firstname", "Lastname");

   // Deallocate memory for the object
   delete pName;
   pName = NULL;
}

Beispiel: new Operator

Wenn Sie die Platzierungsform des new Operators verwenden (das Formular mit mehr Argumenten als die Größe), unterstützt der Compiler keine Platzierungsform des delete Operators, wenn der Konstruktor eine Ausnahme auslöst. Beispiel:

// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
   A(int) { throw "Fail!"; }
};
void F(void) {
   try {
      // heap memory pointed to by pa1 will be deallocated
      // by calling ::operator delete(void*).
      A* pa1 = new A(10);
   } catch (...) {
   }
   try {
      // This will call ::operator new(size_t, char*, int).
      // When A::A(int) does a throw, we should call
      // ::operator delete(void*, char*, int) to deallocate
      // the memory pointed to by pa2.  Since
      // ::operator delete(void*, char*, int) has not been implemented,
      // memory will be leaked when the deallocation can't occur.

      A* pa2 = new(__FILE__, __LINE__) A(20);
   } catch (...) {
   }
}

int main() {
   A a;
}

Initialisieren von Objekten, die zugeordnet sind new

Ein optionales new-initializer Feld ist in der Grammatik für den new Operator enthalten. Mit diesem Feld können neue Objekte mit benutzerdefinierten Konstruktoren initialisiert werden. Weitere Informationen dazu, wie die Initialisierung erfolgt, finden Sie unter Initialisierer. Das folgende Beispiel veranschaulicht die Verwendung eines Initialisierungsausdrucks mit dem new Operator:

// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

int main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double { 43.0 };
    // ...
}

In diesem Beispiel wird das Objekt CheckingAcct mithilfe des new Operators zugewiesen, es wird jedoch keine Standardinitialisierung angegeben. Der Standardkonstruktor für die Klasse Acct()wird also aufgerufen. Anschließend wird das Objekt SavingsAcct auf die gleiche Weise zugewiesen, mit der Ausnahme, dass es explizit auf 34.98 initialisiert wird. Da 34.98 vom Typ doubleist, wird der Konstruktor, der ein Argument dieses Typs verwendet, aufgerufen, um die Initialisierung zu behandeln. Schließlich wird der Nicht-Klassentyp HowMuch auf 43.0 initialisiert.

Wenn ein Objekt einen Klassentyp aufweist und diese Klasse Konstruktoren hat (wie im vorherigen Beispiel), kann das Objekt vom new Operator nur initialisiert werden, wenn eine dieser Bedingungen erfüllt ist:

  • Die im Initialisierer angegebenen Argumente stimmen mit den Argumenten eines Konstruktors überein.

  • Die Klasse verfügt über einen Standardkonstruktor (einen Konstruktor, der ohne Argumente aufgerufen werden kann).

Die explizite Initialisierung pro Element kann nicht ausgeführt werden, wenn Arrays mithilfe des new Operators zugewiesen werden. Nur der Standardkonstruktor, falls vorhanden, wird aufgerufen. Weitere Informationen finden Sie unter Standardargumente.

Wenn die Speicherzuweisung fehlschlägt (operator new gibt den Wert 0 zurück), erfolgt keine Initialisierung. Dieses Verhalten schützt vor Versuchen, Daten zu initialisieren, die nicht vorhanden sind.

Wie bei Funktionsaufrufen wird die Reihenfolge, in der initialisierte Ausdrücke ausgewertet werden, nicht definiert. Darüber hinaus sollten Sie sich nicht darauf verlassen, dass diese Ausdrücke vollständig ausgewertet werden, bevor die Speicherzuweisung erfolgt. Wenn die Speicherzuweisung fehlschlägt und der new Operator null zurückgibt, werden einige Ausdrücke im Initialisierer möglicherweise nicht vollständig ausgewertet.

Lebensdauer der zugeordneten Objekte new

Objekte, die dem new Operator zugeordnet sind, werden nicht zerstört, wenn der Bereich, in dem sie definiert sind, beendet wird. Da der new Operator einen Zeiger auf die objekte zurückgibt, die er zuweist, muss das Programm einen Zeiger mit geeignetem Bereich definieren, um auf diese Objekte zuzugreifen und sie zu löschen. Beispiel:

// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
    }

    delete [] AnotherArray; // Error: pointer out of scope.
    delete [] AnArray;      // OK: pointer still in scope.
}

Sobald der Zeiger AnotherArray den Gültigkeitsbereich in dem Beispiel verlässt, kann das Objekt nicht mehr gelöscht werden.

Funktionsweise von new

Der new-expression (Ausdruck, der den new Operator enthält) führt drei Dinge aus:

  • Sucht und reserviert Speicher für das zuzuweisende Objekt bzw. die zuzuweisenden Objekte. Wenn diese Phase abgeschlossen ist, wird der richtige Speicherplatz zugewiesen, aber es ist noch kein Objekt.

  • Initialisiert das/die Objekt(e). Sobald die Initialisierung abgeschlossen wurde, sind genügend Informationen vorhanden, damit der zugeordnete Speicher ein Objekt sein kann.

  • Gibt einen Zeiger auf die Objekte eines zeigertyps zurück, der von new-type-id oder type-id. Das Programm verwendet diesen Zeiger, um auf das neu zugeordnete Objekt zuzugreifen.

Der new Operator ruft die Funktion operator newauf. Für Arrays eines beliebigen Typs und für Objekte, die keine class, structoder union Typen sind, wird eine globale Funktion aufgerufen, ::operator newum Speicher zuzuweisen. Klassentypobjekte können ihre eigene operator new statische Memberfunktion pro Klasse definieren.

Wenn der Compiler auf den new Operator trifft, um ein Objekt vom Typ Tzuzuweisen, gibt er einen Aufruf T::operator new( sizeof(T) ) aus oder, wenn kein benutzerdefinierter operator new Definiert ist. ::operator new( sizeof(T) ) So kann der new Operator die richtige Speichermenge für das Objekt zuordnen.

Hinweis

Das argument ist operator new vom Typ std::size_t. Dieser Typ wird in direct.h, <malloc.h>>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h, <string.h>> und <time.h> definiert.<

Eine Option in der Grammatik ermöglicht die Spezifikation ( new-placement siehe Grammatik für new Operator). Der Parameter kann nur für benutzerdefinierte Implementierungen operator newverwendet werden. Er new-placement ermöglicht es, zusätzliche Informationen an operator new. Ein Ausdruck mit einem new-placement Feld, z T *TObject = new ( 0x0040 ) T; . B. wird übersetzt, T *TObject = T::operator new( sizeof( T ), 0x0040 ); wenn Klasse T Member operator newhat, andernfalls in T *TObject = ::operator new( sizeof( T ), 0x0040 );.

Die ursprüngliche Absicht des new-placement Felds bestand in der Möglichkeit, hardwareabhängige Objekte an benutzerdefinierten Adressen zuzuordnen.

Hinweis

Obwohl im vorherigen Beispiel nur ein Argument im new-placement Feld angezeigt wird, gibt es keine Einschränkung, wie viele zusätzliche Argumente auf diese Weise übergeben operator new werden können.

Auch wenn operator new für einen Klassentyp Tdefiniert wurde, können Sie den globalen Operator new explizit verwenden, wie in diesem Beispiel:

T *TObject = ::new TObject;

Der Bereichsauflösungsoperator (::) erzwingt die Verwendung des globalen new Operators.

Siehe auch

Ausdrücke mit unären Operatoren
Schlüsselwörter
new und delete Operatoren