2009-10-21 10 views
8

Me gustaría utilizar diferentes instancias de una clase de asignador personalizado STL para administrar diferentes espacios de memoria, y luego poder especificar una instancia de asignador a un contenedor STL de modo que cada contenedor solo extraiga de su espacio de memoria asignado. Pero no veo cómo puedo hacer eso. Veo cómo puedo pasar un tipo de asignador a los parámetros de plantilla de un contenedor STL, pero quiero algo similar a pasar una instancia de asignador al constructor de un contenedor STL. ¿Hay alguna manera de hacer esto en STL?Asignadores personalizados STL para administrar diferentes espacios de memoria

Respuesta

17

Desafortunadamente los asignadores de STL no pueden tener estado (o al menos tienen que tener mucho cuidado de cómo se usa ese estado): cada instancia de un tipo de asignador en particular debe ser equivalente para que los contenedores de STL funcionen efectivamente con ellos. No recuerdo los detalles en este momento, pero sé que Scott Meyers discute extensamente este problema en "Effective STL", artículo 10: tenga en cuenta las convenciones y restricciones del asignador.

Sin embargo, puede ha templated asignadores de que son muy similares con las diferencias entre los asignadores de ser encapsulados en el tipo asignador y utilizar diferentes 'instanciaciones' del molde asignador (cada plantilla 'instanciación' es un tipo diferente) . De nuevo, mi recuerdo es que Meyers discute esto bastante claramente.

Por ejemplo ver este párrafo de un artículo de Anthony Aue, "Improving Performance with Custom Pool Allocators for STL":

Una advertencia potencialmente más grave es que, desde el asignador utiliza datos no estáticos, no es técnicamente estándar compatible, porque la norma requiere que los asignadores de la misma tipo ser equivalente. Ver STL efectivo (Ítem 10) para una explicación completa del problema. Esto equivale a requerir que un asignador para un tipo dado sea capaz de desasignar la memoria asignada por cualquier otra instancia de un asignador para ese tipo. Para muchos usos de contenedores estándar, este requisito es innecesario (algunos podrían decir Draconian). Sin embargo, hay dos casos donde este requisito es absolutamente necesario: list :: splice y swap(). El caso de swap() es especialmente grave porque es necesario para implementar ciertas operaciones en contenedores de una manera segura (consulte Excepcional C++, elemento 12). Técnicamente, el swap podría (y en algunos casos,) implementarse frente a asignadores que no se comparan por igual: los elementos podrían copiarse o los asignadores podrían intercambiarse junto con los datos, pero este no es siempre el caso. Por esta razón, si está utilizando swap() o list :: splice, debe asegurarse de usar HoldingPolicySingleton; de lo contrario, te encontrarás con un comportamiento realmente desagradable.

Véase también la discusión de Stephan T. Lavavej en this newsgroup thread.

Voy a actualizar más tarde esta noche si alguien más no da los detalles mientras tanto.

+2

Vale la pena señalar, sin embargo, que C++ 0x requerirá soporte para asignadores desiguales. –

+1

Tiene razón, vale la pena señalar: preguntas frecuentes de Stroustup sobre C++ 0x "Distribuidores de alcance": http://www.research.att.com/~bs/C++0xFAQ.html#scoped-allocator –

+0

+1 - Ojalá pudiera responder esta respuesta más. Los asignadores en STL han sido bastante novatos-hostiles, atrayendo más errores esotéricos que la funcionalidad de contribución. – Fox

0

Quizás podría codificar un conjunto de tipos de asignadores que contienen un apuntador estático para separar los espacios de memoria.

Luego, cuando el contenedor de STL construye su asignador, el asignador utiliza la memoria asignada a ese asignador.

Para simplificar, suponga que desea utilizar dos espacios de memoria. Crea dos tipos de asignador, uno para cada espacio. Pase el tipo de asignador a los constructores de contenedores STL según sea necesario.

6

Los contenedores STL le permiten pasar el asignador como un argumento para el constructor.

Por ejemplo, aquí son los constructores adecuados para el vector:

explicit vector(const Allocator& = Allocator()); 
explicit vector(size_type n, const T& value = T(), 
    const Allocator& = Allocator()); 
template <class InputIterator> 
vector(InputIterator first, InputIterator last, 
    const Allocator& = Allocator()); 

Por defecto, sólo tiene que utilizar un factor de imputación por defecto construido.

Cuestiones relacionadas