Espacios de nombres
Variantes
Acciones

operador new, operador new[]

De cppreference.com
< cpp‎ | memory‎ | new
 
 
Biblioteca de servicios
 
Gestión de memoria dinámica
Punteros inteligentes
(C++11)
(C++11)
(C++11)
(hasta C++17)
(C++11)
(C++23)
Asignadores de memoria
Recursos de memoria
Almacenamiento no inicializado
Algoritmos de memoria no inicializada
Algoritmos restringidos de memoria no inicializada
Apoyo para recolección de basura
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
Misceláneos
(C++20)
(C++11)
(C++11)
 
 
Definido en el archivo de encabezado <new>
funciones de asignación reemplazables

[[nodiscard]]

(desde C++20)
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) (desde C++17)
void* operator new[]( std::size_t count, std::align_val_t al );
(4) (desde C++17)
funciones de asignación reemplazables que no lanzan

noexcept

(desde C++11)

[[nodiscard]]

(desde C++20)
void* operator new  ( std::size_t count, const std::nothrow_t& tag );
(5)
void* operator new[]( std::size_t count, const std::nothrow_t& tag );
(6)
void* operator new  ( std::size_t count,
                      std::align_val_t al, const std::nothrow_t& );
(7) (desde C++17)
void* operator new[]( std::size_t count,
                      std::align_val_t al, const std::nothrow_t& );
(8) (desde C++17)
funciones de asignación de ubicación que no asignan

noexcept

(desde C++11)

[[nodiscard]]

(desde C++20)
void* operator new  ( std::size_t count, void* ptr );
(9)
void* operator new[]( std::size_t count, void* ptr );
(10)
funciones de asignación de ubicación definidas por el usuario
void* operator new  ( std::size_t count, user-defined-args... );
(11)
void* operator new[]( std::size_t count, user-defined-args... );
(12)
void* operator new  ( std::size_t count,
                      std::align_val_t al, user-defined-args... );
(13) (desde C++17)
void* operator new[]( std::size_t count,
                      std::align_val_t al, user-defined-args... );
(14) (desde C++17)
funciones de asignación específicas de la clase
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) (desde C++17)
void* T::operator new[]( std::size_t count, std::align_val_t al );
(18) (desde C++17)
funciones de asignación de ubicación específicas de la clase
void* T::operator new  ( std::size_t count, user-defined-args... );
(19)
void* T::operator new[]( std::size_t count, user-defined-args... );
(20)
void* T::operator new  ( std::size_t count,
                         std::align_val_t al, user-defined-args... );
(21) (desde C++17)
void* T::operator new[]( std::size_t count,
                         std::align_val_t al, user-defined-args... );
(22) (desde C++17)

Asigna el número de bytes requerido. Estas funciones de asignación se llaman por las expresiones new para asignar memoria en la cual se inicializa un nuevo objeto . También pueden llamarse usando la sintaxis de llamada a función regular.

1) Se llama por las expresiones new sin formato de array para asignar el almacenamiento requerido para un solo objeto. La implementación de la biblioteca estándar asigna count bytes de la reserva disponible. En caso de falla, la implementación de la biblioteca estándar llama al puntero de función devuelto por std::get_new_handler y repite los intentos de asignación hasta que el nuevo controlador no regrese o se convierta en un puntero nulo, momento en el cual lanza std::bad_alloc. Se requiere que esta función devuelva un puntero adecuadamente alineado para apuntar a un objeto del tamaño solicitado.
2) Se llama por las expresiones new[] con formato de array para asignar todo el almacenamiento requerido para un array (incluido un posible costo adicional de la expresión new). La implementación estándar de la biblioteca llama a la versión (1).
3) Se llama por las expresiones new sin formato de array para asignar el almacenamiento requerido para un solo objeto cuyo requisito de alineación excede a __STDCPP_DEFAULT_NEW_ALIGNMENT__.
4) Se llama por las expresiones new[] con formato de array para asignar todo el almacenamiento requerido para un array de objetos cuyo requisito de alineación excede a __STDCPP_DEFAULT_NEW_ALIGNMENT__.
5) Se llama por las expresiones new sin formato de array, que no lanzan excepciones. La implementación de la biblioteca estándar llama a la versión (1) y devuelve un puntero nulo en caso de error en lugar de propagar la excepción.
6) Se llama por las expresiones new[] con formato de array que no lanzan excepciones. La implementación de la biblioteca estándar llama a la versión (2) y devuelve un puntero nulo en caso de error en lugar de propagar la excepción.
7) Se llama por las expresiones new sin formato de array que no lanzan excepciones, cuando el requisito de alineación del objeto excede a __STDCPP_DEFAULT_NEW_ALIGNMENT__. La implementación de la biblioteca estándar llama a la versión (3) y devuelve un puntero nulo en caso de error en lugar de propagar la excepción.
8) Se llama por las expresiones new[] con formato de array que no lanzan excepciones cuando el requisito de alineación de los elementos del array excede a __STDCPP_DEFAULT_NEW_ALIGNMENT__. La implementación de la biblioteca estándar llama a la versión (4) y devuelve un puntero nulo en caso de error en lugar de propagar la excepción.
9) Se llama por la expresión new de ubicación de un solo objeto estándar. La implementación de la biblioteca estándar no realiza ninguna acción y devuelve ptr sin modificar. El comportamiento no está definido si esta función se llama a través de una expresión new de ubicación y ptr es un puntero nulo.
10) Se llama por la expresión new de ubicación con formato de array estándar. La implementación de la biblioteca estándar no realiza ninguna acción y devuelve ptr sin modificar. El comportamiento no está definido si esta función se llama a través de una expresión new de ubicación y ptr es un puntero nulo.
11) Si se define, se llama por la expresión new de ubicación personalizada de un solo objeto con la signatura coincidente. Si se define una versión específica de la clase (19), esta se llama, dándole preferencia sobre (11). Si ni (11) ni (19) se proporcionan por el usuario, la expresión new de ubicación está mal formada.
12) Si se define, se llama por la expresión new de ubicación con formato de array con la signatura coincidente. Si se define una versión específica de la clase (20), esta se llama, dándole preferencia sobre (12). Si ni (12) ni (20) se proporcionan por el usuario, la expresión new de ubicación está mal formada.
13) Si se define, se llama por la expresión new de ubicación personalizada de un solo objeto con la signatura coincidente si los requerimientos de alineación del objeto exceden a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si se define una versión específica de la clase ((15) o (17)), se llama en su lugar. Si no se proporciona ni una versión específica de la clase ni un formato global de ubicación que soporte alineación, en su lugar se busca el formato (11) sin soporte de alineación.
14) Si se define, se llama por la expresión new de ubicación personalizada con formato de array con la signatura coincidente si el requerimiento de alineación del elemento excede a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si se define una versión específica de la clase ((16) o (18)), se llama en su lugar. Si no se proporciona ni una versión específica de la clase ni un formato global de ubicación que soporte alineación, en su lugar se busca el formato (12) sin soporte de alineación.
15) Si se define, se llama por las expresiones new habituales de un solo objeto si se asigna un objeto de tipo T.
16) Si se define, se llama por las expresiones new[] habituales si se asigna un array de objetos de tipo T.
17) Si se define, se llama por las expresiones new habituales de un solo objeto si se asigna un objeto de tipo T si sus requerimientos de alineación exceden a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si no se proporciona esta sobrecarga, pero se provee el formato (15) de miembro que no soporta un asignador, en su lugar se llama a la sobrecarga de miembro que no soporta un asignador.
18) Si se define, se llama por las expresiones new[] habituales si se asigna un array de objetos de tipo T si sus requerimientos de alineación exceden a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si no se proporciona esta sobrecarga, pero se provee el formato (16) de miembro que no soporta un asignador, en su lugar se llama a la sobrecarga de miembro que no soporta un asignador.
19) Si se define, se llama por la expresión new de ubicación personalizada de un solo objeto con la signatura coincidente si se asigna un objeto de tipo T.
20) Si se define, se llama por la expresión new[] de ubicación personalizada con formato de array con la signatura coincidente si se asigna un array de objetos de tipo T.
21) Si se define, se llama por la expresión new de ubicación personalizada de un solo objeto con la signatura coincidente si se asigna un objeto de tipo T si sus requerimientos de alineación exceden a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si no se proporciona esta sobrecarga, pero se provee el formato (19) de miembro que no soporta un asignador, en su lugar se llama a la sobrecarga de miembro que no soporta un asignador.
22) Si se define, se llama por la expresión new[] de ubicación personalizada con formato de array con la signatura coincidente si se asigna un array de objetos de tipo T si sus requerimientos de alineación exceden a __STDCPP_DEFAULT_NEW_ALIGNMENT__. Si no se proporciona esta sobrecarga, pero se provee el formato (20) de miembro que no soporta un asignador, en su lugar se llama a la sobrecarga de miembro que no soporta un asignador.

Contenido

[editar] Parámetros

count - Número de bytes a asignar.
ptr - Puntero a un área de memoria en la cual initializer el objeto.
tag - Etiqueta de desambiguación utilizada para seleccionar sobrecargas que no lanzan excepciones.
al - Alineamiento a usar. El comportamiento es indefinido si éste no es un valor de alineamiento válido.

[editar] Valor de retorno

1-4) Puntero no nulo a memoria adecuadamente alineada de tamaño al menos size.
5-8) Puntero no nulo a memoria adecuadamente alineada de tamaño al menos size, o puntero nulo si hubo falla al asignar.
9-10) ptr.
11-22) Lo mismo (1-4) si la función no regresa si hubo falla en la asignación, de otra forma, lo mismo que (5-8).

[editar] Excepciones

1-4) Lanza std::bad_alloc u otra excepción derivada de std::bad_alloc (desde C++11) si sucede una falla al asignar memoria.
11-22) Lo mismo que (1-4) si la función no regresa si ocurre una falla durante la asignación, de otra forma, lo mismo que (5-8).

[editar] Reemplazos globales

Las versiones (1-4) se declaran implícitamente en cada unidad de traducción aun cuando el archivo de encabezado <new> no se incluya. Las versiones (1-8) son reemplazables: una función miembro proporcionada por el usuario con la misma signatura definida en cualquier parte del programa, en cualquier archivo fuente, reemplaza a la versión por defecto. Su declaración no necesita ser visible.

El comportamiento es indefinido si se proporciona más de un reemplazo en el programa para cualquier función de asignación reemplazable, o si un reemplazo se define con el especificador inline. El programa está mal formado si se define un reemplazo en un espacio de nombres que no sea el espacio de nombres global, o si se define como una función estática no miembro en el ámbito global.

La implementación de la biblioteca estándar para las versiones nothrow (5-8) llama directamente a las versiones correspondientes que sí lanzan excepciones (1-4). La implementación de la biblioteca estándar para las versiones de array que lanzan excepciones (2,4) llama directamente a la versión correspondiente de un solo objeto (1,3). Por lo tanto, reemplazar las funciones de asignación de un solo objeto que lanzan excepciones es suficiente para tratar con todas las asignaciones.

(desde C++11)
#include <cstdio>
#include <cstdlib>
#include <new>
// reemplazo de un conjunto mínimo de funciones:
void* operator new(std::size_t sz) {
    std::printf("se ha llamado al op new global, size = %zu\n", sz);
    void *ptr = std::malloc(sz);
    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}
void operator delete(void* ptr) noexcept
{
    std::puts("se ha llamado al op delete global");
    std::free(ptr);
}
int main() {
     int* p1 = new int;
     delete p1;
 
     int* p2 = new int[10]; // se garantiza que llama al reemplazo en C++11
     delete[] p2;
}

Posible salida:

se ha llamado al op new global, size = 4
se ha llamado al op delete global
se ha llamado al op new global, size = 40
se ha llamado al op delete global

Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("los formatos de ubicación", versiones (11-14)) pueden declararse en el ámbito global como es habitual, y se llaman por los formatos de ubicación de expresiones new coincidentes.

Los formatos de ubicación del operador new de la biblioteca estándar que no asignan (9-10), no pueden reemplazarse y solamente pueden ser personalizados si la expresión new de ubicación no utilizó la nueva sintaxis ::new, al proporcionar un new de ubicación específico de la clase (19,20) con una signatura coincidente: void* T::operator new(size_t, void*) o void* T::operator new[](size_t, void*).

El formato de ubicación void* operator new(std::size_t, std::size_t) no se permite porque la signatura coincidente de la función de desasignación, void operator delete(void*, std::size_t), es una función de desasignación habitual (no de ubicación).

(desde C++14)

[editar] Sobrecargas específicas de la clase

Las funciones de asignación de memoria tanto de objetos únicos como arrays pueden definirse como funciones miembro estáticas públicas de una clase (versiones (15-18)). Si se definen, estas funciones de asignación se llaman por las expresiones new para asignar memoria para objetos únicos y arrays de esa clase, a menos que la expresión new haya utilizado el formato ::new, que pasa por alto la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas funciones: independientemente de si se usa o no, la función de asignación es una función miembro estática.

La expresión new busca el nombre de la función de asignación apropiada primero en el ámbito de la clase, y después en el ámbito global. Observa que debido a las reglas de búsqueda de nombres, cualquier función de asignación declarada en el ámbito de la clase oculta todas las funciones de asignación globales para las expresiones new que intenten asignar objetos de esta clase.

Al asignar objetos y arrays de objetos cuya alineación excede de __STDCPP_DEFAULT_NEW_ALIGNMENT__, se realiza la resolución de sobrecarga dos veces: primero, para las signaturas de funciones que soportan alineación, luego para las signaturas de funciones que no soportan alineación. Esto significa que si una clase con alineación extendida tiene una función de asignación específica de la clase que no soporta alineación, esa es la función que se llamará, y no la función de asignación global que soporta alineación. Esto es intencional: se espera que la función miembro de la clase conozca la mejor manera de cómo tratar con esa clase.

(desde C++17)
#include <iostream>
// funciones de asignación específicas de la clase
struct X {
    static void* operator new(std::size_t sz)
    {
        std::cout << "new personalizado con " << sz << " bytes" << '\n';
        return ::operator new(sz);
    }
    static void* operator new[](std::size_t sz)
    {
        std::cout << "new personalizado con " << sz << " bytes" << '\n';
        return ::operator new(sz);
    }
};
int main() {
     X* p1 = new X;
     delete p1;
     X* p2 = new X[10];
     delete[] p2;
}

Posible salida:

new personalizado con 1 bytes
new personalizado con 10 bytes

Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("formatos de ubicación"), también pueden definirse como miembros de la clase (19-22)). Cuando la expresión new con la signatura coincidente busca la función de asignación correspondiente para llamarla, comienza en el ámbito de la clase antes de examinar el ámbito global, y si se proporciona un new de ubicación específico de la clase, se llama.

Al asignar objetos y arrays de objetos cuya alineación excede de __STDCPP_DEFAULT_NEW_ALIGNMENT__, la resolución de sobrecarga para los formatos de ubicación se realiza dos veces, de manera similar a los formatos regulares: primero, para las signaturas de función que soportan alineación, luego para las signaturas de función que no soportan alineación.

(desde C++17)
#include <stdexcept>
#include <iostream>
struct X {
    X() { throw std::runtime_error(""); }
    // new de ubicación personalizado
    static void* operator new(std::size_t sz, bool b) {
        std::cout << "se ha llamado a new de ubicación personalizado, b = " << b << '\n';
        return ::operator new(sz);
    }
    // delete de ubicación personalizado
    static void operator delete(void* ptr, bool b)
    {
        std::cout << "se ha llamado a delete de ubicación personalizado, b = " << b << '\n';
        ::operator delete(ptr);
    }
};
int main() {
   try {
     X* p1 = new (true) X;
   } catch(const std::exception&) { }
}

Salida:

se ha llamado a new de ubicación personalizado, b = 1
se ha llamado a delete de ubicación personalizado, b = 1

Si operator new al nivel de la clase es una plantilla de función, debe tener un tipo de retorno de void*, el primer argumento debe ser std::size_t, y debe tener dos o más parámetros. En otras palabras, solamente los formatos de ubicación pueden ser plantillas.

[editar] Véase también

Funciones de desasignación.
(función) [editar]
Obtiene el nuevo controlador actual.
(función) [editar]
Registra un controlador nuevo.
(función) [editar]
(en desuso en C++17)(eliminado en C++20)
Obtiene almacenamiento sin inicializar.
(plantilla de función) [editar]
Asigna memoria
(función) [editar]
Asigna memoria alineada
(función) [editar]

[editar] Referencias

  • El estándar C++11 (ISO/IEC 14882:2011):
  • 18.6 Administración de memoria dinámica [support.dynamic]