¿Cuáles son los usos de la construcción C++ "colocación nueva"?
memory new-operator (12)
Lo he usado al construir objetos en un segmento de memoria compartida.
Acabo de enterarme de la construcción de C ++ llamada "colocación nueva". Le permite controlar exactamente a dónde señala un puntero en la memoria. Se parece a esto:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)];
void* place = memory;
Fred* f = new(place) Fred(); // Create a pointer to a Fred(),
// stored at "place"
// The pointers f and place will be equal
...
}
(ejemplo de C ++ FAQ Lite )
En este ejemplo, el puntero de Fred será igual al place
.
Lo he visto usado en el código de nuestro equipo una o dos veces. En tu experiencia, ¿qué hace este constructo? ¿Tienen otros lenguajes de puntero construcciones similares? Para mí, parece una reminiscencia de la equivalence
en FORTRAN, que permite que variables dispares ocupen la misma ubicación en la memoria.
Es útil cuando construyes tu propio contenedor como objetos.
Por ejemplo, si crearas un vector. Si reserva espacio para una gran cantidad de objetos, desea asignar la memoria con algún método que no invoque al constructor del objeto (como new char [sizeof (object) * reserveSize]). Luego, cuando la gente comienza a agregar objetos al vector, utiliza la colocación nueva para copiarlos en la memoria asignada.
template<typename T>
class SillyVectorExample
{
public:
SillyVectorExample()
:reserved(10)
,size(0)
,data(new char[sizeof(T) * reserved])
{}
void push_back(T const& object)
{
if (size >= reserved)
{
// Do Somthing.
}
// Place a copy of the object into the data store.
new (data+(sizeof(T)*size)) T(object);
++size;
}
// Add other methods to make sure data is copied and dealllocated correctly.
private:
size_t reserved;
size_t size;
char* data;
};
PD. No estoy abogando por hacer esto. Este es solo un ejemplo simplificado de cómo pueden funcionar los contenedores.
La colocación nueva se puede usar para crear uniones seguras de tipo, como la variant
de Boost.
La clase de unión contiene un búfer tan grande como el tipo más grande que se especifica que contiene (y con una alineación suficiente). Coloca new
objetos s en el búfer según sea necesario.
Le permite hacer su propia gestión de memoria. Por lo general, esto le proporcionará, en el mejor de los casos, un rendimiento marginalmente mejorado, pero a veces es una gran ganancia. Por ejemplo, si su programa utiliza una gran cantidad de objetos de tamaño estándar, es posible que desee crear un grupo con una gran asignación de memoria.
Este tipo de cosas también se hizo en C, pero como no hay constructores en C, no requirió ningún soporte de idiomas.
Puede ser útil cuando se busca memoria en un archivo en el disco duro, lo que se podría hacer al manipular objetos grandes.
También se usa para la programación integrada, donde los dispositivos IO a menudo se asignan a direcciones de memoria específicas
Yo uso esta construcción al hacer C ++ en modo kernel.
Uso el asignador de memoria en modo núcleo y construyo el objeto en el fragmento asignado.
Todo esto está envuelto en clases y funciones, pero al final hago una colocación nueva.
me parece una forma de asignar un objeto en la pila ...
La colocación nueva NO se trata de hacer que los punteros sean iguales (¡solo puede usar asignación para eso!).
La colocación nueva es para construir un objeto en una ubicación particular. Hay tres formas de construir un objeto en C ++, y la colocación nueva es la única que le da control explícito sobre dónde ese objeto "vive". Esto es útil para varias cosas, incluida la memoria compartida, la entrada / salida de dispositivos de bajo nivel y la implementación del pool / allocator de memoria.
Con la asignación de pila, el objeto se construye en la parte superior de la pila, donde sea que esté actualmente.
Con el nuevo "regular", el objeto se construye en una dirección efectivamente arbitraria en el montón, según lo gestionado por la biblioteca estándar (a menos que haya reemplazado el operador nuevo).
La ubicación nueva dice "construya un objeto en esta dirección específicamente", y su implementación es simplemente una sobrecarga de operador nuevo que devuelve el puntero que se le pasa, como un medio para llegar al resto de la maquinaria del nuevo operador, que construye un objeto en la memoria devuelto por la nueva función del operador.
También vale la pena señalar que la nueva función del operador se puede sobrecargar con argumentos arbitrarios (como cualquier otra función). Estos otros argumentos se pasan a través de la sintaxis "new (arg 2, arg3, ..., argN)". Arg1 siempre se pasa implícitamente como "sizeof (lo que sea que estés construyendo)".
Lo he usado para crear objetos basados en la memoria que contiene mensajes recibidos de la red.
Al controlar la ubicación exacta, puede alinear cosas en la memoria y, a veces, esto se puede utilizar para mejorar el rendimiento de la recuperación de la CPU / caché. En realidad, nunca lo vi en uso, aunque
La colocación nueva permite al desarrollador asignar la memoria del trozo de memoria preasignado. Si el sistema es más grande, los desarrolladores utilizan la ubicación nueva. Ahora estoy trabajando en un software de aviónica más grande; allí asignamos la gran cantidad de memoria que se requiere para la ejecución de la aplicación al inicio. Y utilizamos la ubicación nueva para asignar la memoria donde sea necesario. Aumenta el rendimiento a cierta cantidad.