2008-12-12 10 views
12

Acabo de enterarme de la construcción de C++ llamada "ubicación nueva". Le permite controlar exactamente a dónde señala un puntero en la memoria. Se ve así:¿Cuáles son los usos de la construcción C++ "placement new"?

#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 this de Fred será igual a 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 equivalence en FORTRAN, que permite que variables dispares ocupen la misma ubicación en la memoria.

Respuesta

4

Uso este constructo al hacer C++ en modo kernel.

Utilizo el asignador de memoria del 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.

1

Puede ser útil cuando se busca memoria en un archivo en el disco duro, lo que se puede hacer al manipular objetos grandes.

+0

¿Puede profundizar en eso? Útil para paginación? ¿O útil para enviar de nuevo? Veo la paginación de nuevo, sin imaginar el aviso. – ApplePieIsGood

5

La colocación nueva se puede utilizar para crear uniones de tipo seguro, como Boost variant.

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 los objetos new en el búfer según sea necesario.

12

También se utiliza para la programación incrustado, donde los dispositivos IO a menudo se asignan a teclas específicas para la memoria

14

Se 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.

+1

El problema que está describiendo debe resolverse utilizando el asignador de memoria adecuado, la colocación de sobrecarga nueva podría no ser la mejor medida. –

+0

Correcto: al usar la biblioteca de plantillas. De lo contrario, hay una ubicación nueva. – jmucchiello

+0

Claro, hay muchos lugares en C++ donde ahora hay una mejor manera de hacerlo. No he escrito eliminar [] en años, por ejemplo. Sin embargo, hay una gran cantidad de código antiguo que sí utiliza la ubicación nueva y tal. –

0

me parece como una manera de asignar un objeto en la pila ..

+0

Bueno, eso es lo que hace vainilla nueva, pero por lo general no se especifica dónde está en la pila. –

+0

Tommy: estás pensando en el montón –

+0

Bueno, en la pregunta publicada anteriormente, de hecho termina terminando en la pila, porque el buffer creado está en la pila. Pero ese no tiene que ser el caso. Tal vez un mejor ejemplo habría utilizado la memoria asignada en el montón con malloc() ... – ApplePieIsGood

7

Lo he utilizado en la construcción de objetos en un segmento de memoria compartida.

7

Es útil cuando construyes tu propio contenedor como objetos.

Por ejemplo, si creara 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; 
}; 

PS. No estoy abogando por hacer esto. Este es solo un ejemplo simplificado de cómo pueden funcionar los contenedores.

+0

¿Tiene algún ejemplo más concreto de cuándo realmente usaría esto? –

+0

¿Qué quiere decir más concreto? Los contenedores son un buen ejemplo. Estoy seguro de que los contenedores STL que necesitan reservar espacio utilizarán la colocación nueva de alguna forma (probablemente a través de las asignaciones, pero no he buscado, así que esto es solo una suposición). –

1

La ubicació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.

4

La colocación nueva NO se trata de hacer que los punteros sean iguales (¡solo puede usar la asignación para eso!).

La ubicación nueva es para construir un objeto en una ubicación determinada. 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 asignación de pila, el objeto se construye en la parte superior de la pila, donde sea que esté actualmente.

Con "nuevo" normal, el objeto se construye en una dirección efectivamente arbitraria en el montón, como lo gestiona la biblioteca estándar (a menos que haya reemplazado el operador nuevo).

La ubicación nueva dice "crea 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 medio para llegar al resto de la maquinaria del nuevo operador, que construye un objeto en la memoria devuelta por la nueva función del operador.

También vale la pena señalar que la nueva función del operador puede sobrecargarse 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)".

0

Lo he usado para crear objetos basados ​​en la memoria que contiene mensajes recibidos de la red.

2

Al controlar la ubicación exacta, puede alinear las cosas en la memoria y esto puede a veces utilizarse para mejorar el rendimiento de la recuperación de la CPU/caché. Nunca lo vi en uso, aunque

Cuestiones relacionadas