read mid metodos how from define c++ string compiler-construction memory-management

metodos - mid c++ string



std:: implementación de cadena en GCC y su sobrecarga de memoria para cadenas cortas (4)

Bueno, al menos con GCC 4.4.5, que es lo que tengo a mano en esta máquina, std::string es un typdef para std::basic_string<char> , y basic_string se define en /usr/include/c++/4.4.5/bits/basic_string.h . Hay un montón de direccionamiento indirecto en ese archivo, pero a lo que se reduce es que std::string s no vacío almacena un puntero a uno de estos:

struct _Rep_base { size_type _M_length; size_type _M_capacity; _Atomic_word _M_refcount; };

Seguido en memoria por los datos de cadena reales. Por lo tanto, std::string tendrá al menos tres palabras de sobrecarga para cada cadena, más cualquier sobrecarga por tener una capacity mayor que `length (probablemente no, dependiendo de cómo construyas tus cadenas - puedes verificar preguntando la capacity() método).

También habrá una sobrecarga de su asignador de memoria por hacer muchas asignaciones pequeñas; No sé qué GCC usa para C ++, pero suponiendo que es similar al asignador dlmalloc que usa para C, podrían ser al menos dos palabras por asignación, más espacio para alinear el tamaño con un múltiplo de al menos 8 bytes.

Actualmente estoy trabajando en una aplicación para una plataforma con poca memoria que requiere un std :: set de muchas cadenas cortas (> 100,000 cadenas de 4 a 16 caracteres cada una). Recientemente hice la transición de este conjunto de std :: string a const char * para ahorrar memoria y me preguntaba si realmente estaba evitando toda esa sobrecarga por cadena.

Intenté usar lo siguiente:

std::string sizeTest = "testString"; std::cout << sizeof(sizeTest) << " bytes";

Pero solo me dio una salida de 4 bytes, lo que indica que la cadena contiene un puntero. Soy consciente de que las cadenas almacenan sus datos en un char * internamente, pero pensé que la clase de cadena tendría una sobrecarga adicional.

¿La implementación de GCC de std :: string incurre en más sobrecarga de lo que indica sizeof (std :: string)? Más importante aún, ¿es significativo sobre este tamaño de conjunto de datos?

Aquí están los tamaños de los tipos relevantes en mi plataforma (es de 32 bits y tiene 8 bits por byte):

char: 1 bytes
nulo *: 4 bytes
char *: 4 bytes
std :: string: 4 bytes


He realizado algunas comparaciones sobre std :: string overhead. En general es de unos 48 bytes! Eche un vistazo al artículo en mi blog: http://jovislab.com/blog/?p=76


Si se garantiza que "> 100,000 cadenas de 4-16 caracteres cada una", entonces no use std :: string. En su lugar, escriba su propia clase ShortString. Es interesante que "sizeof (std :: string) == 4", ¿cómo es eso posible? ¿Qué son sizeof (char) y sizeof (void *)?


Voy a suponer que está en una plataforma de 32 bits, 8 bits por byte. También voy a adivinar que al menos en la versión de gcc que estás usando, que están usando una implementación de referencia contada para std :: string. El tamaño de 4 bytes que ve es un puntero a una estructura que contiene el recuento de referencia y los datos de la cadena (y cualquier estado del asignador, si corresponde).

En este diseño de gcc, la única cadena "corta" tiene tamaño == 0, en cuyo caso puede compartir una representación con cualquier otra cadena vacía. De lo contrario, obtienes una cadena de COW refcounted.

Para investigar esto usted mismo, codifique un asignador que realice un seguimiento de la cantidad de memoria que asigna y desasigna, y cuántas veces. Utilice este asignador para investigar la implementación del contenedor que le interesa.