c++ tuples language-lawyer padding

c++ - std:: tuple sizeof, ¿es una optimización perdida?



tuples language-lawyer (3)

std :: tuple sizeof, ¿es una optimización perdida?

Sí.

¿Es posible que una implementación haga esto [?]

Sí.

[¿Está] prohibido por alguna regla en el estándar?

¡No!

Al leer [tuple] , no hay ninguna restricción impuesta a la implementación para almacenar los miembros en orden de argumento de plantilla.

De hecho, cada pasaje que puedo encontrar parece ir muy lejos para evitar hacer referencia alguna al orden de declaración de miembro: get<N>() se usa en la descripción de la semántica operativa. Otras palabras se expresan en términos de "elementos" en lugar de "miembros", lo que parece una abstracción bastante deliberada.

De hecho, algunas implementaciones aparentemente almacenan los miembros en orden inverso , al menos, probablemente simplemente por la forma en que usan la herencia de forma recursiva para desempaquetar los argumentos de la plantilla (y porque, como se indicó anteriormente, se les permite).

Sin embargo, hablando específicamente de su optimización hipotética, no conozco ninguna implementación que no almacene elementos en [alguna función trivial de] el orden dado por el usuario; Supongo que sería "difícil" llegar a tal orden y proporcionar la maquinaria para std::get , al menos en comparación con la cantidad de ganancia que obtendría al hacerlo. Si está realmente preocupado por el relleno, por supuesto, puede elegir su orden de elementos con cuidado para evitarlo (en alguna plataforma dada), como lo haría con una clase (sin profundizar en el mundo de los atributos "empaquetados"). (Una tupla "llena" podría ser una propuesta interesante ...)

He verificado todos los compiladores principales, y sizeof(std::tuple<int, char, int, char>) es 16 para todos ellos. Presumiblemente, simplemente ordenan los elementos en la tupla, por lo que se desperdicia algo de espacio debido a la alineación.

Si tuple almacena elementos internos como: int, int, char, char , entonces su tamaño podría ser 12.

¿Es posible que una implementación haga esto, o está prohibido por alguna regla en el estándar?


Otra razón para no hacerlo: algunas arquitecturas, incluida x86, tienen un modo de indexación que puede abordar una base de dirección + tamaño × índice en una sola instrucción, pero solo cuando el tamaño es una potencia de 2. O puede ser un poco más rápido hacer una carga o almacenar alineado a un límite de 16 bytes. Esto podría hacer que el código que aborda las matrices de std::tuple poco más rápido y más compacto si agregan cuatro bytes de relleno.


Sí, es posible y ha sido (principalmente) hecho por R. Martinho Fernandes . Solía ​​tener un blog llamado Flaming Danger Zone , que ahora está inactivo por alguna razón, pero sus fuentes aún están disponibles en github .

Aquí están las cuatro partes de la serie Size Matters sobre este tema exacto: 1 , 2 , 3 , 4 .

Es posible que desee verlos sin formato, ya que github no entiende el marcado de resaltado de C ++ utilizado y representa los fragmentos de código como líneas ilegibles.

Básicamente, calcula una permutación para los índices de tupla a través del metaprograma de plantilla C ++ 11, que clasifica los elementos por alineación en orden no ascendente, almacena los elementos de acuerdo con ellos y luego los aplica al índice en cada acceso.