resueltos programacion programa funciones fuente example ejercicios ejemplos con codigo clases cadenas array c++ c++11 memory-management stdstring

c++ - programacion - std::string example



std:: string sin asignación gratuita de memoria de tienda (4)

Tengo una pregunta muy similar a

¿Cómo asigno una cadena std :: en la pila usando la implementación de cadena de glibc?

pero creo que vale la pena preguntar de nuevo.

Quiero una std::string con almacenamiento local que se desborda en la tienda gratuita. std::basic_string proporciona un asignador como parámetro de plantilla, por lo que parece que lo que hay que hacer es escribir un asignador con almacenamiento local y usarlo para parametrizar basic_string , así:

std::basic_string< char, std::char_traits<char>, inline_allocator<char, 10> > x("test");

Traté de escribir la clase inline_allocator que funcionaría de la manera inline_allocator : reserva 10 bytes para el almacenamiento, y si basic_string necesita más de 10 bytes, llama a ::operator new() . No pude hacer que funcione. En el curso de la ejecución de la línea de código anterior, mi biblioteca de cadenas estándar de GCC 4.5 llama al constructor de copias para inline_allocator 4 veces. No es claro para mí que haya una manera sensata de escribir el constructor de copia para inline_allocator .

En el otro hilo de StackOverflow, Eric Melski proporcionó este enlace a una clase en Chromium:

http://src.chromium.org/svn/trunk/src/base/stack_container.h

lo cual es interesante, pero no es un reemplazo std::string para std::string , porque envuelve std::basic_string en un contenedor para que tenga que llamar a un operator->() sobrecargado operator->() para obtener std::basic_string .

No puedo encontrar ninguna otra solución a este problema. ¿Podría ser que no hay una buena solución? Y si eso es cierto, ¿los conceptos std::basic_string y std::allocator muy mal? Quiero decir, parece que este debería ser un caso de uso muy simple y básico para std::basic_string y std::allocator . Supongo que el concepto std::allocator está diseñado principalmente para pools, pero creo que debería cubrir esto también.

Parece que la semántica de movimiento rvalue-reference en C ++ 0x podría hacer posible inline_allocator , si la biblioteca de cadenas se vuelve a escribir para que basic_string use el constructor de movimientos de su asignador en lugar del constructor de copias. ¿Alguien sabe cuál es la perspectiva para ese resultado?

Mi aplicación necesita construir un millón de pequeñas series ASCII por segundo, así que terminé escribiendo mi propia clase de cadena de longitud fija basada en Boost.Array , que funciona bien, pero esto todavía me molesta.


Andrei Alexandrescu, extraordinario programador de C ++ que escribió "Modern C ++ Design" escribió una vez un excelente artículo sobre la construcción de diferentes implementaciones de cadenas con sistemas de almacenamiento personalizables. Su artículo ( vinculado aquí ) describe cómo puede hacer lo que describió anteriormente como un caso especial de un sistema mucho más general que puede manejar todo tipo de requisitos inteligentes de asignación de memoria. Esto no habla mucho sobre std::string y se centra más en una clase de cadena completamente personalizada, pero es posible que desee examinarlo ya que hay algunas gemas reales en la implementación.


C ++ 2011 realmente te va a ayudar aquí :)

El hecho es que el concepto de allocator en C ++ 03 quedó paralizado. Uno de los requisitos era que un asignador de tipo A debería poder desasignar la memoria de cualquier otro asignador del tipo A ... Desafortunadamente, este requisito también está en desacuerdo con los asignadores con estado, cada uno conectado a su propio grupo.

Howard Hinnant (que administra el subgrupo STL del comité C ++ y está implementando un nuevo STL desde cero para C ++ 0x) ha explorado asignadores basados ​​en la pila en su sitio web , de lo que podría obtener inspiración.


Creo que el código de Chromium simplemente envuelve las cosas en un bonito caparazón. Pero puede obtener el mismo efecto sin usar el contenedor de envoltura de Chromium.

Debido a que el objeto asignador se copia con tanta frecuencia, debe contener una referencia o puntero a la memoria. Entonces, lo que tendría que hacer es crear el búfer de almacenamiento, crear el objeto asignador y luego llamar al constructor std :: string con el asignador.

Va a ser mucho más bohemio que utilizar la clase contenedora, pero debería tener el mismo efecto.

Puedes ver un ejemplo del método detallado (aún usando las cosas de cromo) en mi pregunta sobre los vectores de pila .


Esto es generalmente innecesario. Se llama "optimización de cadena corta", y la mayoría de las implementaciones de std::string ya lo incluyen. Puede ser difícil de encontrar, pero por lo general está allí de todos modos.

Solo por ejemplo, aquí está la pieza relevante de sso_string_base.h que es parte de MinGW:

enum { _S_local_capacity = 15 }; union { _CharT _M_local_data[_S_local_capacity + 1]; size_type _M_allocated_capacity; };

El miembro _M_local_data es el relevante: espacio para que almacene (hasta) 15 caracteres (más un terminador NUL) sin asignar ningún espacio en el montón.

Si la memoria sirve, la biblioteca Dinkumware incluida con VC ++ asigna espacio para 20 caracteres, aunque ha pasado un tiempo desde que miré, así que no puedo jurar (y rastrear gran parte de cualquier cosa en sus encabezados tiende a ser un dolor, por lo que Prefiero evitar mirar si puedo).

En cualquier caso, daría buenas probabilidades de que haya estado involucrado en ese tiempo de pase tan popular conocido como optimización prematura.