2010-09-22 31 views
14

¿Cuál es la sobrecarga en la estructura de cadena que causa que sizeof() sea 32?¿Por qué sizeof (string) == 32?

+5

Si abre el encabezado '' de su plataforma, puede ver exactamente por qué 'std :: string' es ese tamaño. @Queso: 'sizeof' produce el tamaño de un objeto _en bytes_. –

+2

Si sizeof devuelve el número de bits en el puntero, entonces su compilador está roto –

+0

@Queso: sizeof() devuelve bytes, no bits.Un puntero de 32 bytes es una dirección de 256 bits – mkb

Respuesta

39

Algunas implementaciones de std::string guardan secuencias muy pequeñas directamente en la pila en una matriz de tamaño estático char en lugar de utilizar el almacenamiento de pila dinámica. Esto permite evitar asignaciones de montón para muchos objetos de cadena pequeños y mejora la localidad de referencia.

Además, habrá un miembro std::size_t para guardar el tamaño de las cadenas y un puntero (potencialmente no utilizado, vea arriba) para el almacenamiento del montón.

+1

Ah. ¿Y por qué fue esto downvoted? –

+0

Parece ser yo, pero no lo hice intencionalmente. ¡Lo siento por eso! – Bill

+0

@Bill: ¡no te preocupes! Ya me pasó a mí también. –

9

std::string normalmente contiene un búfer para la "optimización de cadena pequeña" --- si la cadena es menor que el tamaño del búfer, no se requiere asignación de pila.

+0

Donde "normalmente" == "en Windows" ;-) –

+2

Los compiladores de Windows no son los únicos que hacen la optimización de cadena pequeña –

+0

Claro, pero si no está dispuesto a nombrarlos, entonces es difícil juzgar si esto es un comportamiento "típico", o simplemente lo llama por el hecho de que es el comportamiento de una implementación común (y presumiblemente de otros). –

3

Depende de la biblioteca. No debe confiar en el tamaño de los objetos std::string porque es probable que cambie en diferentes entornos (obviamente entre diferentes proveedores de bibliotecas estándar, pero también entre diferentes versiones de la misma biblioteca).

Tenga en cuenta que las implementaciones std::string están escritas por personas que han optimizado para una variedad de casos de uso, lo que generalmente lleva a 2 representaciones internas, una para cadenas cortas (pequeño búfer interno) y otra para cadenas largas (asignación externa buffer). La sobrecarga está asociada a la celebración de ambos dentro de cada objeto std::string.

4

Mi conjetura es:

class vector 
{ 
    char type; 
    struct Heap 
    { 
     char* start; 
     char* end; 
     char* allocatedEnd; 
    }; 
    struct Stack 
    { 
     char size; 
     char data[27]; 
    } 
    union 
    { 
     Stack stackVersion; 
     Heap heapVersion; 
    } version; 
}; 

Pero apuesto a que hay cientos de maneras de hacerlo.

+0

awww ... no cuenta de referencia? ¿Qué pasó con el plegado? –

+0

@ErikAronesty Hubo una fase en la que se intentó el recuento de referencias con 'std :: string', pero se hizo evidente que no era muy eficiente (había varios artículos) y la optimización de cadenas cortas se hizo popular. –

1

P: ¿Por qué es un perro amarillo? A: No es necesariamente.

El tamaño de un objeto (a?) Std :: string depende de la implementación. Acabo de comprobar MS VC++ 2010. Efectivamente usa 32 bytes para std :: string. Hay una unión de 16 bytes que contiene el texto de la cadena, si cabe, o un puntero para acumular el almacenamiento de cadenas más largas. Si los implementadores hubieran elegido mantener cadenas de 18 bytes en el objeto de cadena en lugar de en el montón, el tamaño sería de 34 bytes. Los otros 16 bytes comprenden una tara, que contiene cosas tales como la longitud de la cadena y la cantidad de memoria asignada actualmente para la cadena.

Una implementación diferente siempre puede asignar memoria desde el montón. Dicha implementación indudablemente requerirá menos memoria para el objeto de cadena.

2

En g ++ 5.2 (por ejemplo, en g ++ 4.9, es diferente) una cadena se define básicamente como:

class string { 
    char* bufferp; 
    size_t length; 
    union { 
    char local_buffer[16]; 
    size_t capacity; 
    }; 
}; 

En un equipo ordinario esto añade hasta 32 bytes (8 + 8 + dieciséis).

La definición real es, por supuesto

typedef basic_string<char> string; 

pero la idea es la misma.