operator new, operator new[]
| Definido en el encabezado <new>
|
||
| Funciones de asignación reemplazables |
||
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 que no lanzan excepciones reemplazables |
||
void* operator new ( std::size_t count, const std::nothrow_t& tag );
|
(5) | (noexcept desde C++11) |
void* operator new[]( std::size_t count, const std::nothrow_t& tag );
|
(6) | (noexcept desde C++11) |
void* operator new ( std::size_t count, std::align_val_t al,
const std::nothrow_t& tag ) noexcept;
|
(7) | (desde C++17) |
void* operator new[]( std::size_t count, std::align_val_t al,
const std::nothrow_t& tag ) noexcept;
|
(8) | (desde C++17) |
| Funciones de asignación de colocación que no asignan |
||
void* operator new ( std::size_t count, void* ptr );
|
(9) | (noexcept desde C++11) (constexpr desde C++26) |
void* operator new[]( std::size_t count, void* ptr );
|
(10) | (noexcept desde C++11) (constexpr desde C++26) |
| Funciones de asignación de colocación definidas por el usuario |
||
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) | (desde C++17) |
void* operator new[]( std::size_t count,
std::align_val_t al, /* args... */ );
|
(14) | (desde C++17) |
| Funciones de asignación específicas de 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 colocación específicas de clase |
||
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) | (desde C++17) |
void* T::operator new[]( std::size_t count,
std::align_val_t al, /* args... */ );
|
(22) | (desde C++17) |
Intenta asignar el número de bytes solicitado, y la solicitud de asignación puede fallar (incluso si el número de bytes solicitado es cero). Estas funciones de asignación son llamadas por las new expresiones new para asignar memoria en la que luego se inicializará el nuevo objeto. También pueden ser llamadas usando la sintaxis de llamada a función regular.
new estándar. No realiza ninguna acción y devuelve ptrptr sin modificar.newnew de colocación y ptrptr es un puntero nulo, el comportamiento no está definido.new expresiones new.Las sobrecargas (1-4) se declaran implícitamente en cada unidad de traducción incluso si el encabezado <new> no está incluido.
Consulte la new expresión new para los criterios de selección de sobrecarga.
Parámetros
| count | - | número de bytes a asignar |
| ptr | - | puntero a un área de memoria para inicializar el objeto |
| tag | - | etiqueta de desambiguación utilizada para seleccionar sobrecargas no lanzadoras |
| al | - | alineación a utilizar, un valor inválido conduce a comportamiento indefinido |
Valor de retorno
Excepciones
Reemplazos globales
Las sobrecargas (1-8) son reemplazables. Los efectos de las versiones predeterminadas son:
- Si el intento tiene éxito, devuelve un puntero al almacenamiento asignado, el almacenamiento está alineado a la alineación fundamental(hasta C++17)el almacenamiento está alineado a
__STDCPP_DEFAULT_NEW_ALIGNMENT__(desde C++17). - De lo contrario, si actualmente no hay un new-handler instalado, lanza std::bad_alloc.
- De lo contrario, llama al new-handler actualmente instalado.
- Si el new-handler regresa, comienza otro intento de asignación.
- De lo contrario, sale de la invocación actual.
operator new(count).al.operator new(count, al).tag.
- Si la llamada regresa normalmente, devuelve el resultado de esa llamada.
- De lo contrario, devuelve un puntero nulo.
|
En implementaciones independientes, está definido por la implementación si las versiones predeterminadas de (1-8) satisfacen los comportamientos requeridos anteriormente. Se recomienda que en las implementaciones independientes, si alguna de estas versiones predeterminadas cumple con los requisitos de una implementación alojada, todas deberían hacerlo. |
(desde C++26) |
Reemplazo global de operators new/delete:
#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;
}
Posible salida:
// 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)
Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("formas de colocación", versiones (11-14)) pueden declararse en el ámbito global como de costumbre, y son llamadas por las formas de colocación coincidentes de las expresiones new.
Las formas de colocación no asignadoras de la biblioteca estándar de operator new (9,10) no pueden ser reemplazadas y solo pueden personalizarse si la expresión de colocación new no utilizó la sintaxis ::new, proporcionando una colocación new específica de clase (19,20) con firma coincidente: void* T::operator new(std::size_t, void*) o void* T::operator new[](std::size_t, void*).
|
La forma de colocación |
(desde C++14) |
Sobrecargas específicas de clase
Tanto las funciones de asignación de un solo objeto como las de asignación de arreglos pueden definirse como funciones miembro estáticas públicas de una clase (versiones (15-18)). Si se definen, estas funciones de asignación son llamadas por expresiones new para asignar memoria para objetos individuales y arreglos de esta clase, a menos que la expresión new haya usado la forma ::new que omite la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas funciones: ya sea que se use 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 luego en el ámbito global. Nótese que, según 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 intentan asignar objetos de esta clase.
|
Al asignar objetos y arreglos de objetos cuyo alineamiento excede |
(desde C++17) |
|
Al asignar objetos y arreglos de objetos cuyo alineamiento no excede |
(desde 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;
}
Posible salida:
custom new for size 1
custom new[] for size 10
Las sobrecargas de operator new y operator new[] con parámetros adicionales definidos por el usuario ("formas de ubicación"), también pueden definirse como miembros de clase (19-22)). Cuando la expresión de ubicación new con la firma coincidente busca la función de asignación correspondiente para llamar, comienza en el ámbito de la clase antes de examinar el ámbito global, y si la ubicación específica de clase new se proporciona, es llamada.
|
Al asignar objetos y arreglos de objetos cuyo alineamiento excede |
(desde C++17) |
|
Al asignar objetos y arreglos de objetos cuyo alineamiento no excede |
(desde 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&)
{}
}
Salida:
custom placement new called, b = 1
custom placement delete called, b = 1
Si operator new a nivel de clase es una función plantilla, debe tener el tipo de retorno de void*, el primer argumento std::size_t, y debe tener dos o más parámetros. En otras palabras, solo las formas de ubicación pueden ser plantillas.
Notas
Aunque el placement no asignador new ( 9,10 ) no puede ser reemplazado, una función con la misma firma puede definirse en el ámbito de la clase como se describió anteriormente. Además, se permiten sobrecargas globales que parecen placement new pero toman un tipo de puntero no void como segundo argumento, por lo que el código que quiere asegurar que se llame al verdadero placement new (ej. std::allocator::construct ), debe usar :: new y también convertir el puntero a void * .
Si el comportamiento de una función de desasignación no satisface las restricciones predeterminadas, el comportamiento es indefinido.
|
Las siguientes funciones deben ser seguras para hilos (thread-safe):
Las llamadas a estas funciones que asignan o desasignan una unidad particular de almacenamiento ocurren en un único orden total, y cada llamada de desasignación happens-before la siguiente asignación (si existe) en este orden. |
(desde C++11) |
No está especificado si las versiones de biblioteca de
operator new
realizan llamadas a
std::malloc
o
std::aligned_alloc
(desde C++17)
.
Para cargar un archivo grande, el mapeo de archivos mediante funciones específicas del sistema operativo, por ejemplo,
mmap
en POSIX o
CreateFileMapping
(
A
/
W
) junto con
MapViewOfFile
en Windows, es preferible a asignar un búfer para la lectura de archivos.
| Macro de prueba de características | Valor | Std | Característica |
|---|---|---|---|
__cpp_lib_freestanding_operator_new
|
202306L
|
(C++26) | soporte freestanding para operator new reemplazable [1] |
0
|
(C++26) | sin soporte freestanding | |
__cpp_lib_constexpr_new
|
202406L
|
(C++26) | constexpr placement new y new [ ] |
- ↑ Formalmente, esta macro se expande a 202306L si todas las versiones por defecto de las funciones de asignación global reemplazables cumplen con los requisitos de una implementación hospedada.
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 521 | C++98 |
cualquier clase derivada de
std::bad_alloc
podría ser lanzada,
incluso si la base std::bad_alloc es ambigua o inaccesible |
la excepción lanzada debe coincidir
con un manejador de tipo std::bad_alloc |
| LWG 9 | C++98 |
múltiples llamadas para asignar cero
bytes podrían devolver el mismo puntero |
solo permitido si todos los punteros
previamente devueltos han sido pasados a funciones de desasignación |
| LWG 206 | C++98 |
reemplazar las funciones de asignación reemplazables no
afectaba los comportamientos por defecto de las correspondientes funciones de asignación reemplazables que no lanzan excepciones |
los comportamientos por defecto
cambian en consecuencia |
| LWG 404 | C++98 |
los reemplazos de las funciones de asignación
reemplazables podían declararse inline |
prohibido, no se requiere diagnóstico |
Referencias
- Estándar C++23 (ISO/IEC 14882:2024):
-
- 17.7 Gestión de memoria dinámica [support.dynamic]
- Estándar C++20 (ISO/IEC 14882:2020):
-
- 17.6 Gestión de memoria dinámica [support.dynamic]
- Estándar C++17 (ISO/IEC 14882:2017):
-
- 21.6 Gestión de memoria dinámica [support.dynamic]
- Estándar C++14 (ISO/IEC 14882:2014):
-
- 18.6 Gestión de memoria dinámica [support.dynamic]
- Estándar C++11 (ISO/IEC 14882:2011):
-
- 18.6 Gestión de memoria dinámica [support.dynamic]
- Estándar C++03 (ISO/IEC 14882:2003):
-
- 18.4 Gestión de memoria dinámica [lib.support.dynamic]
- Estándar C++98 (ISO/IEC 14882:1998):
-
- 18.4 Gestión de memoria dinámica [lib.support.dynamic]
Véase también
|
[static]
(C++23)
|
asigna memoria usando
Allocator
(función miembro estática pública de
std::generator<Ref,V,Allocator>::promise_type
)
|
|
funciones de desasignación
(función) |
|
|
(C++11)
|
obtiene el manejador de memoria actual
(función) |
|
registra un nuevo manejador
(función) |
|
|
(obsoleto en C++17)
(eliminado en C++20)
|
obtiene almacenamiento no inicializado
(plantilla de función) |
|
asigna memoria
(función) |
|
|
(C++17)
|
asigna memoria alineada
(función) |