newOperador (C++)

Intenta asignar e inicializar un objeto o matriz de objetos de un tipo especificado o de un marcador de posición, y devuelve un puntero con tipo adecuado y distinto de cero al objeto (o al objeto inicial de la matriz).

Sintaxis

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

Comentarios

Si no se ejecuta correctamente, new devuelve cero o arroja una excepción. Para más información, consulte Los operadores new y delete. Puede cambiar este comportamiento predeterminado escribiendo una rutina de control de excepciones personalizada y llamando a la función de biblioteca en tiempo de ejecución _set_new_handler con el nombre de función como su argumento.

Para obtener más información sobre cómo crear un objeto en el montón administrado en C++/CLI y C++/CX, consulte gcnew.

Nota:

Las extensiones de componentes de Microsoft C++ (C++/CX) proporcionan compatibilidad para que la palabra clave new agregue entradas de ranura de vtable. Para más información, consulte new(nueva ranura en vtable)

Cuando new se utiliza para asignar memoria para un objeto de clase de C++, se llama al constructor del objeto después de que se asigna la memoria.

Utilice el operador delete para desasignar la memoria asignada con el operador new. Use el operador delete[] para eliminar una matriz asignada por el operador new.

En el ejemplo siguiente se asigna y se libera una matriz bidimensional de caracteres de tamaño dim por 10. Al asignar una matriz multidimensional, todas las dimensiones excepto la primera deben ser expresiones constantes que se evalúen como valores positivos. La dimensión de matriz situada más a la izquierda puede ser cualquier expresión que se evalúe como un valor positivo. Al asignar una matriz mediante el operador new, la primera dimensión puede ser cero; el operador new devuelve un puntero único.

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

El elemento type-id no puede contener declaraciones de clase const o volatile ni declaraciones de enumeración. La siguiente expresión tiene un formato incorrecto:

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

El operador new no asigna tipos de referencia porque no son objetos.

El operador new no se puede usar para asignar una función, pero sí para asignar punteros a funciones. En el ejemplo siguiente se asigna y se libera una matriz de siete punteros a funciones que devuelven enteros.

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

Si se usa el operador new sin ningún argumento adicional y compila con la opción /GX, /EHa o /EHs, el compilador generará un código para llamar al operador delete si el constructor produce una excepción.

En la lista siguiente se describen los elementos de la gramática de new:

new-placement
Proporciona una manera de pasar argumentos extra si se sobrecarga new.

type-id
Especifica el tipo que se va a asignar; puede ser un tipo integrado o un tipo definido por el usuario. Si la especificación de tipo es compleja, puede ir entre paréntesis para forzar el orden de enlace. El tipo puede ser un marcador de posición (auto) cuyo tipo viene determinado por el compilador.

new-initializer
Proporciona un valor para el objeto inicializado. No se pueden especificar los inicializadores para las matrices. El operador new creará las matrices de objetos únicamente si la clase tiene un constructor predeterminado.

noptr-new-declarator
Especifica los límites de una matriz. Al asignar una matriz multidimensional, todas las dimensiones excepto la primera deben ser expresiones constantes que se evalúen como valores positivos convertibles a std::size_t. La dimensión de matriz situada más a la izquierda puede ser cualquier expresión que se evalúe como un valor positivo. El attribute-specifier-seq se aplica al tipo de matriz asociado.

Ejemplo: asignar y liberar una matriz de caracteres

En el ejemplo de código siguiente se asigna una matriz de caracteres y un objeto de clase CName y después se liberan.

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

Por ejemplo: operador new

Si se usa el formato de ubicación del operador new (el formato con más argumentos que tamaño), el compilador no admite un formato de ubicación del operador delete si el constructor produce una excepción. Por ejemplo:

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

Inicializar objetos asignados con new

Un campo new-initializer opcional se incluye en la gramática del operador new. Este campo permite que los nuevos objetos se inicialicen con constructores definidos por el usuario. Para obtener más información sobre cómo se realiza la inicialización, consulte Inicializadores. En el ejemplo siguiente se muestra la forma de usar una expresión de inicialización con el operador 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 };
    // ...
}

En este ejemplo, el objeto CheckingAcct se asigna usando el operador new, pero no se especifica ninguna inicialización predeterminada. De esta forma, se llama al constructor predeterminado para la clase Acct(). El objeto SavingsAcct se asigna de la misma manera, salvo que se inicializa explícitamente en 34,98. Dado que 34,98 es de tipo double, se llama al constructor que toma un argumento de ese tipo para controlar la inicialización. Finalmente, el tipo HowMuch que no es de clase se inicializa en 43,0.

Si un objeto es de un tipo de clase y esa clase tiene constructores (como en el ejemplo anterior), el objeto se puede inicializar mediante el operador new solo si se cumple una de estas condiciones:

  • Los argumentos proporcionados en el inicializador concuerdan con los argumentos de un constructor.

  • La clase tiene un constructor predeterminado (un constructor al que se puede llamar sin argumentos).

No se puede realizar ninguna inicialización explícita por elemento al asignar matrices mediante el operador new; solo se llama al constructor predeterminado, si existe. Para obtener más información, consulte Argumentos predeterminados.

Si se produce un error en la asignación de memoria (operator new devuelve un valor de 0), no se realiza ninguna inicialización. Este comportamiento protege contra intentos de inicializar datos que no existen.

Como sucede con las llamadas a funciones, no se define el orden en que se evalúan las expresiones inicializadas. Además, no se debe dar por hecho que estas expresiones se hayan evaluado totalmente antes de que se produzca la asignación de memoria. Si se produce un error en la asignación de memoria y el operador new devuelve cero, es posible que algunas expresiones del inicializador no se hayan evaluado totalmente.

Duración de objetos asignados con new

Los objetos asignados con el operador new no se destruyen cuando se sale del ámbito en el que se definen. Como el operador new devuelve un puntero a los objetos que asigna, el programa debe definir un puntero con el ámbito adecuado para tener acceso y eliminar esos objetos. Por ejemplo:

// 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 vez que el puntero AnotherArray sale del ámbito en el ejemplo, el objeto ya no se puede eliminar.

Cómo funciona new

La new-expression (expresión que contiene el operador new) hace tres cosas:

  • Busca y reserva el almacenamiento para el objeto o los objetos a asignar. Cuando se completa esta fase, se asigna la cantidad correcta de almacenamiento, pero todavía no es un objeto.

  • Inicializa los objetos. Una vez completada la inicialización, hay suficiente información presente para que el almacenamiento asignado sea un objeto.

  • Devuelve un puntero a los objetos de un tipo de puntero derivado de new-type-id a type-id. El programa usa este puntero para tener acceso al objeto recién asignado.

El operador new invoca la función operator new. Para las matrices de cualquier tipo y para los objetos que no son de tipo class, struct o union, se llama a una función global, ::operator new, para asignar almacenamiento. Los objetos de tipo de clase pueden definir su propia función de miembro estática operator new clase por clase.

Cuando el compilador se encuentra con el operador newque asigna un objeto de tipo T, emite una llamada a T::operator new( sizeof(T) ) o, si no hay ningún operator new definido por el usuario, a ::operator new( sizeof(T) ). Así es como el operador new puede asignar la cantidad de memoria correcta para el objeto.

Nota:

El argumento para operator new es de tipo std::size_t. Este tipo se define en <direct.h>, <malloc.h>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, and <time.h>.

Una opción de la gramática permite la especificación de new-placement (consulte la gramática para new Operador). El parámetro new-placement solo se puede utilizar para las implementaciones definidas por el usuario deoperator new; permite pasar información adicional a operator new. Una expresión con un campo new-placement tal como T *TObject = new ( 0x0040 ) T; se convierte en T *TObject = T::operator new( sizeof( T ), 0x0040 ); si la clase T tiene el miembro operator new; si no, se convierte en T *TObject = ::operator new( sizeof( T ), 0x0040 );.

La intención original del campo new-placement es permitir que los objetos dependientes de hardware se asignen a direcciones especificadas por el usuario.

Nota:

Aunque en el ejemplo anterior solo se muestra un argumento en el campo new-placement, no hay ninguna restricción sobre cuántos argumentos adicionales se pueden pasar a operator new de esta forma.

Incluso cuando operator new se ha definido para un tipo de clase T, se puede usar explícitamente el operador global new, como en este ejemplo:

T *TObject = ::new TObject;

El operador de resolución de ámbito (::) fuerza el uso del operador global new.

Consulte también

Expresiones con operadores unarios
Palabras clave
operadores new y delete