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 reemplazables que no lanzan excepciones
|
||
|
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 sin asignación de memoria
|
||
|
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 ubicación definidas por el usuario
|
||
|
void
*
operator new
(
std::
size_t
count,
/* args... */
)
;
|
(11) | |
|
void
*
operator new
[
]
(
std::
size_t
count,
/* argumentos... */
)
;
|
(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 ubicació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, /* argumentos... */ ) ; |
(22) | (desde C++17) |
Intenta asignar el número solicitado de bytes, y la solicitud de asignación puede fallar (incluso si el número solicitado de bytes es cero). Estas funciones de asignación son llamadas por new expressions para asignar memoria en la cual el nuevo objeto sería entonces inicializado. También pueden ser llamadas usando la sintaxis regular de llamada a función.
Sobrecargas ( 1-4 ) se declaran implícitamente en cada unidad de traducción incluso si el <new> header no está incluido.
Consulte new expression para los criterios de selección de sobrecarga.
Contenidos |
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
Sobrecargas ( 1-8 ) son reemplazables . Los efectos de las versiones por defecto son:
- Si el intento es exitoso, devuelve un puntero al almacenamiento asignado.
- En caso contrario, si actualmente no hay un new-handler instalado, lanza std::bad_alloc .
-
En caso contrario, llama al new-handler actualmente instalado.
- Si el new-handler retorna, inicia otro intento de asignación.
- En caso contrario, finaliza la invocación actual.
- Si la llamada retorna normalmente, devuelve el resultado de esa llamada.
- En caso 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 las implementaciones independientes, si alguna de estas versiones predeterminadas cumple con los requisitos de una implementación hospedada, todas deberían hacerlo. |
(since C++26) |
Reemplazo de operadores
operator
s
new
/
delete
globales:
#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; }
Salida posible:
// 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 es usual, y son llamadas por las correspondientes
formas de colocación
de las expresiones
new
.
Las formas de ubicación sin asignación de la biblioteca estándar de
operator new
(
9,10
)
no pueden ser reemplazadas y solo pueden personalizarse si la expresión de ubicación
new
no utilizó la sintaxis
::
new
, proporcionando una ubicación específica de clase
new
(
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 void * operator new ( std:: size_t , std:: size_t ) no está permitida porque la firma coincidente de la función de desasignación, void operator delete ( void * , std:: size_t ) , es una función de desasignación normal (no de colocación). |
(desde C++14) |
Sobrecargas específicas de la clase
Tanto las funciones de asignación de objetos individuales como 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 las expresiones new para asignar memoria para objetos individuales y arreglos de esta clase, a menos que la expresión new utilice la forma :: new que omite la búsqueda en el ámbito de la clase. La palabra clave static es opcional para estas funciones: tanto si se utiliza como si no, la función de asignación es una función miembro estática.
La expresión new busca primero el nombre de la función de asignación apropiada en el ámbito de la clase, y después en el ámbito global. Nótese que, de acuerdo con 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 cuya alineación excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga se realiza dos veces: primero, para las firmas de función conscientes de la alineación, luego para las firmas de función no conscientes de la alineación. Esto significa que si una clase con alineación extendida tiene una función de asignación específica de clase no consciente de la alineación, será esa función la que se llamará, no la función de asignación global consciente de la alineación. Esto es intencional: se espera que el miembro de clase sepa mejor cómo manejar esa clase. |
(desde C++17) |
|
Al asignar objetos y arreglos de objetos cuya alineación no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga se realiza dos veces: primero, para las firmas de función que no consideran la alineación, luego para las firmas de función que sí consideran la alineación. |
(since 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; }
Salida posible:
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 colocación"), también pueden definirse como miembros de clase
(
19-22
)
). Cuando la expresión de colocación
new
con la firma correspondiente 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 se proporciona el
new
de colocación específico de la clase, se llama.
|
Al asignar objetos y arreglos de objetos cuya alineación excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga para las formas de colocación se realiza dos veces al igual que para las formas regulares: primero, para las firmas de funciones conscientes de la alineación, luego para las firmas de funciones no conscientes de la alineación. |
(desde C++17) |
|
Al asignar objetos y arreglos de objetos cuya alineación no excede __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la resolución de sobrecarga para las formas de colocación se realiza dos veces al igual que para las formas regulares: primero, para las firmas de función que no tienen en cuenta la alineación, luego para las firmas de función que sí tienen en cuenta la alineación. |
(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 el operador a nivel de clase
operator new
es una función plantilla, debe tener el tipo de retorno
void
*
, el primer argumento
std::size_t
, y debe tener dos o más parámetros. En otras palabras, solo las formas de colocació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) |