2009-03-17 10 views
7

Para un proyecto mío, estoy escribiendo algunos contenedores STL desde cero (tengo mis razones). Dado que estoy imitando la funcionalidad y las interfaces de la STL tan de cerca, estoy haciendo todo lo posible para cumplir con la política "si tiene el mismo nombre que una construcción estándar, se ajustará a la norma tanto como sea posible".std :: allocator construye/destroy vs. placement new/p-> ~ T()

Así que, por supuesto, mis contenedores toman asignadores como un parámetro de plantilla, lo cual es muy bueno ya que permite algunos esquemas de asignación personalizados. En mi pregunta.

La interfaz std::allocator separa la asignación de memoria de la construcción del objeto. Asimismo, separa la desasignación de la destrucción. Esto tiene sentido ya que de donde obtienes memoria es más o menos irrelevante para construir correctamente un objeto en C++.

Así que hay dos funciones construcción/desasignación se expresan del siguiente a la aplicación por defecto (sacan directamente de un libro):

void construct(pointer p, const T& val) { new(p) T(val); } 
void destroy(pointer p)     { p->~T(); } 

como se puede ver construir simplemente llama a la colocación de nuevo y destruir simplemente llama al destructor .

¿Hay alguna razón para usar esto simplemente usando la colocación nueva y la sintaxis del destructor? ¿Puede un asignador "correcto" implementarlos de otra manera? ¿O tengo la garantía de que todas las implementaciones de asignadores que se ajusten al estándar tendrán métodos de construcción/destrucción implementados de esta manera?

Más al punto, ¿es seguro decir que siempre puedo usar el std::uninitialized_copy y el std::uninitialized_fill para construir los elementos de mis contenedores?

Gracias.

Respuesta

8

El asignador podría agregar instrucciones de registro antes y después de la construcción/destrucción, o cualquier otro efecto secundario que haya querido hacer.

Por supuesto, la construcción real tiene que ocurrir llamando a la colocación de nuevo y el destructor, pero no se dice en el libro de reglas que otra cosa debe suceder en la construcción/destruir funciones

+1

sí, ese es un buen punto, podría ser un buen gancho para el registro "post-asignación/pre-construcción" o el seguimiento de memleak. –

+1

Esta respuesta es correcta pero un poco engañosa. Los efectos secundarios como el registro son en realidad bastante difíciles de hacer con la seguridad de excepción correcta. Más a menudo, la personalización se realiza mediante el ajuste a la nueva expresión incrustada, p. argumentos de constructor Consulte https://groups.google.com/a/isocpp.org/d/topic/std-discussion/yZLnYy_y2z0/discussion – Potatoswatter

2

Esto es solo para ocultar los detalles de la asignación en un método. es decir, proporcionamos las API para construcción y destrucción, en el futuro podemos cambiar la implementación. Ahora estamos usando la ubicación nueva para asignar la memoria, en el futuro si queremos cambiar la asignación solo tenemos que cambiar estos dos métodos.

+0

sí, estoy de acuerdo con ese. Pero tengo curiosidad si el estándar les permite ser cambiado. (especialmente con asignadores personalizados que no tenemos que esperar un nuevo estándar para ...). –

+0

'allocator :: construct' no tiene nada que ver con la asignación, y como todos los asignadores sí (ahora) se asignan, no puedo imaginar por qué harían' construir' cualquier cosa –

Cuestiones relacionadas