new operator (C++)

Tenta di allocare e inizializzare un oggetto o una matrice di oggetti di un tipo specificato o segnaposto e restituisce un puntatore tipizzato e diverso da zero all'oggetto (o all'oggetto iniziale della matrice).

Sintassi

new-expression:
::optnew-placementoptnew-initializernew-type-idnew
::optopt)new-initializertype-id(newnew-placement

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

Osservazioni:

In caso di esito negativo, new restituisce zero o genera un'eccezione. Per altre informazioni, vedere Operatori newe delete . È possibile modificare questo comportamento predefinito scrivendo una routine di gestione delle eccezioni personalizzata e chiamando la funzione della libreria di runtime con il nome della _set_new_handler funzione come argomento.

Per informazioni su come creare un oggetto nell'heap gestito in C++/CLI e C++/CX, vedere gcnew.

Nota

Microsoft C++ Component Extensions (C++/CX) fornisce il supporto per la new parola chiave per aggiungere voci di slot vtable. Per altre informazioni, vedere new (nuovo slot nella tabella virtuale)

Quando new viene usato per allocare memoria per un oggetto classe C++, il costruttore dell'oggetto viene chiamato dopo l'allocazione della memoria.

Usare l'operatore delete per deallocare la memoria allocata dall'operatore new . Usare l'operatore delete[] per eliminare una matrice allocata dall'operatore new .

Nell'esempio viene allocata e successivamente liberata una matrice bidimensionale di caratteri di dimensione dim per 10. Quando si alloca una matrice multidimensionale, tutte le dimensioni tranne la prima devono essere espressioni costanti che restituiscono valori positivi. La dimensione della matrice più a sinistra può essere qualsiasi espressione che restituisce un valore positivo. Quando si alloca una matrice utilizzando l'operatore new , la prima dimensione può essere zero. L'operatore new restituisce un puntatore univoco.

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

type-id Non può contenere constdichiarazioni di classe , volatileo dichiarazioni di enumerazione. L'espressione seguente è in formato non corretto:

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

L'operatore new non alloca i tipi di riferimento perché non sono oggetti.

L'operatore new non può essere usato per allocare una funzione, ma può essere usato per allocare puntatori alle funzioni. Nell'esempio seguente viene allocata e successivamente liberata una matrice di sette puntatori a funzioni che restituiscono numeri interi.

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

Se si usa l'operatore new senza argomenti aggiuntivi e si esegue la compilazione con l'opzione /GX, /EHao /EHs , il compilatore genera il codice per chiamare l'operatore delete se il costruttore genera un'eccezione.

L'elenco seguente descrive gli elementi grammaticali di new:

new-placement
Fornisce un modo per passare argomenti aggiuntivi se si esegue l'overload newdi .

type-id
Specifica il tipo da allocare; può essere un tipo predefinito o definito dall'utente. Se la specifica del tipo è complessa, è possibile racchiuderla tra parentesi per forzare l'ordine di associazione. Il tipo può essere un segnaposto (auto) il cui tipo è determinato dal compilatore.

new-initializer
Fornisce un valore per l'oggetto inizializzato. Non è possibile specificare gli inizializzatori per le matrici. L'operatore new creerà matrici di oggetti solo se la classe ha un costruttore predefinito.

noptr-new-declarator
Specifica i limiti di una matrice. Quando si alloca una matrice multidimensionale, tutte le dimensioni tranne la prima devono essere espressioni costanti che restituiscono valori positivi convertibili in std::size_t. La dimensione della matrice più a sinistra può essere qualsiasi espressione che restituisce un valore positivo. Si attribute-specifier-seq applica al tipo di matrice associato.

Esempio: Allocare e liberare una matrice di caratteri

Nell'esempio di codice che segue vengono allocati una matrice di caratteri e un oggetto della classe CName, quindi vengono successivamente liberati.

// 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;
}

Esempio: new operatore

Se si usa il formato di posizionamento dell'operatore new (il form con più argomenti rispetto alle dimensioni), il compilatore non supporta una forma di posizionamento dell'operatore delete se il costruttore genera un'eccezione. Ad esempio:

// 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;
}

Inizializzazione di oggetti allocati con new

Un campo facoltativo new-initializer è incluso nella grammatica per l'operatore new . Questo campo consente di inizializzare nuovi oggetti con costruttori definiti dall'utente. Per altre informazioni sulla modalità di inizializzazione, vedere Inizializzatori. Nell'esempio seguente viene illustrato come usare un'espressione di inizializzazione con l'operatore new :

// 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 questo esempio l'oggetto CheckingAcct viene allocato usando l'operatore new , ma non viene specificata alcuna inizializzazione predefinita. Viene quindi chiamato il costruttore predefinito per la classe , Acct(). L'oggetto SavingsAcct viene quindi allocato nello stesso modo, ad eccezione del fatto che viene inizializzato in modo esplicito a 34.98. Poiché 34.98 è di tipo double, il costruttore che accetta un argomento di tale tipo viene chiamato per gestire l'inizializzazione. Infine, il tipo HowMuch non di classe viene inizializzato su 43.0.

Se un oggetto è di un tipo di classe e la classe dispone di costruttori (come nell'esempio precedente), l'oggetto può essere inizializzato dall'operatore new solo se viene soddisfatta una di queste condizioni:

  • Gli argomenti forniti nell'inizializzatore corrispondono agli argomenti di un costruttore.

  • La classe dispone di un costruttore predefinito (un costruttore che può essere chiamato senza argomenti).

Non è possibile eseguire l'inizializzazione esplicita per elemento quando si allocano matrici usando l'operatore new . Viene chiamato solo il costruttore predefinito, se presente. Per altre informazioni, vedere Argomenti predefiniti.

Se l'allocazione di memoria non riesce (operator new restituisce un valore pari a 0), non viene eseguita alcuna inizializzazione. Questo comportamento protegge dai tentativi di inizializzare i dati che non esistono.

Come per le chiamate di funzione, l'ordine in cui vengono valutate le espressioni inizializzate non è definito. Inoltre, non è consigliabile basarsi su queste espressioni valutate completamente prima che venga eseguita l'allocazione della memoria. Se l'allocazione di memoria non riesce e l'operatore new restituisce zero, alcune espressioni nell'inizializzatore potrebbero non essere valutate completamente.

Durata degli oggetti allocati con new

Gli oggetti allocati con l'operatore new non vengono eliminati definitivamente quando l'ambito in cui sono definiti viene chiuso. Poiché l'operatore new restituisce un puntatore agli oggetti allocati, il programma deve definire un puntatore con ambito appropriato per accedere ed eliminare tali oggetti. Ad esempio:

// 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.
}

Una volta che il puntatore AnotherArray esce dall'ambito (nell'esempio), l'oggetto non può più essere eliminato.

Come new funziona

( new-expression l'espressione contenente l'operatore new ) esegue tre operazioni:

  • Individua e riserva uno spazio di archiviazione per l'oggetto o gli oggetti da allocare. Al termine di questa fase, viene allocata la quantità corretta di spazio di archiviazione, ma non è ancora un oggetto.

  • Inizializza l'oggetto/gli oggetti. Una volta che l'inizializzazione è stata completata, vi sono informazioni sufficienti affinché l'archiviazione allocata sia un oggetto.

  • Restituisce un puntatore agli oggetti di un tipo di puntatore derivato da new-type-id o type-id. Il programma usa questo puntatore per accedere all'oggetto appena allocato.

L'operatore new richiama la funzione operator new. Per le matrici di qualsiasi tipo e per gli oggetti che non classsono , structo union , viene chiamata una funzione globale, ::operator new, per allocare l'archiviazione. Gli oggetti di tipo classe possono definire la propria operator new funzione membro statica in base alla classe.

Quando il compilatore rileva l'operatore new per allocare un oggetto di tipo T, genera una chiamata a T::operator new( sizeof(T) ) o, se non è definito alcun oggetto definito dall'utente operator new , ::operator new( sizeof(T) ). È così che l'operatore new può allocare la quantità di memoria corretta per l'oggetto.

Nota

L'argomento di operator new è di tipo std::size_t. Questo tipo è definito in <direct.h>, <malloc.h>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h> e <time.h>.

Un'opzione nella grammatica consente la specifica di new-placement (vedere Grammar for new Operator). Il new-placement parametro può essere usato solo per le implementazioni definite dall'utente di operator new. Consente di passare informazioni aggiuntive a operator new. Un'espressione con un new-placement campo, T *TObject = new ( 0x0040 ) T; ad esempio , viene convertita in T *TObject = T::operator new( sizeof( T ), 0x0040 ); se la classe T ha membro operator new, in caso contrario in T *TObject = ::operator new( sizeof( T ), 0x0040 );.

L'intenzione originale del new-placement campo era quella di consentire l'allocazione di oggetti dipendenti dall'hardware a indirizzi specificati dall'utente.

Nota

Anche se l'esempio precedente mostra un solo argomento nel new-placement campo, non esiste alcuna restrizione sul numero di argomenti aggiuntivi che è possibile passare a operator new questo modo.

Anche quando operator new è stato definito per un tipo di Tclasse , è possibile usare l'operatore new globale in modo esplicito, come in questo esempio:

T *TObject = ::new TObject;

L'operatore di risoluzione dell'ambito (::) forza l'uso dell'operatore globale new .

Vedi anche

Espressioni con operatori unari
Parole chiave
newOperatori e delete