2010-04-18 20 views
15

Los estados C++ 0x FCD en la capacidad 23.3.6.2 vector:¿Por qué shrink_to_fit no es vinculante?

void shrink_to_fit(); 

Observaciones: shrink_to_fit es una solicitud no vinculante para reducir la capacidad() para size(). [Nota: la solicitud no es vinculante para permitir la flexibilidad de las optimizaciones específicas de la implementación. — end note]

¿Qué optimizaciones están previstas?

+13

Podría imaginar que algún asignador podría querer asignar en bloques de longitudes fijas. Por lo tanto, si el tamaño del elemento es menor que el tamaño del bloque, aún puede sobreasignar. Solo un poco de adivinación ... –

+1

@Johannes: Si publicaste eso como respuesta, sería mucho más fácil de aclarar. Vea mi comentario para doblar abajo, además no veo cómo un asignador puede comunicar eso al vector (allocate() solo devuelve un puntero), pero supongo que podría ser parcialmente especializado si se usa std :: allocator. Aunque eso me hace preguntarme sobre las especializaciones de los usuarios (aún permitidas, ¿verdad?) Y los conflictos. –

Respuesta

11

Este es un tensas, pero:

Considere asignador de vector que sólo pudo asignar memoria con, digamos, 4 KB granularidad. Entonces no tendría sentido reasignar la memoria si un vector tiene una capacidad de 4096 y un tamaño de 4095, ya que esto no conservaría la memoria, pero desperdiciaría algo de tiempo de CPU para copiar elementos.

+0

Es factible, pero no hay forma en la interfaz de asignación estándar para comunicar esto. (A menos que me haya perdido una adición de 0x) Sin embargo, la reasignación si el tamaño es 4095 y la capacidad es 4096 podría hacerse independientemente, y supongo que tiene sentido, excepto que podría verificarlo si quisiera antes de llamar a shrink_to_fit. –

+0

Bueno, un caso ya especializado es el vector . Los asignadores obviamente tienen al menos una granularidad de 1 byte y, por lo que recuerdo, el vector usa un bit por elemento. Realmente sin importancia, sin embargo. – doublep

+0

vector es una abominación generalmente aceptada como un error.Causa problemas si escribe una plantilla que pueda usar bool y espere una interfaz de contenedor real, y espero que otras especializaciones para vector no se puedan romper de manera similar (de hecho, AFAIK, el estándar lo prohibiría). –

4

Las ideas de redondeo son realmente relevantes, pero indirectamente. La pregunta es "qué optimizaciones están destinadas a permitirse". Eso es hacer algunas suposiciones sobre el proceso de estandarización wrt. optimizaciones. En general, la intención es permitir todas las optimizaciones no observables y algunas más, como la elisión de copia, donde la no llamada del copiador sea observable. En este caso, capacity() != size() podría ser un efecto observable de una optimización, y el estándar lo permite.

En cuanto a las razones para agregar esta latitud, también podría imaginar ignorar una solicitud de contracción cuando capacity() es solo el 101% de size() - ganancias muy pequeñas. Nunca habrá una sola razón precisa, ya que el LWG está formado por muchas personas con muchos puntos de vista. Simplemente existe (hubo) un consenso suficiente de que hay suficientes oportunidades de optimización adicionales creadas al otorgar esta libertad.

+0

Sé que, en general, el estándar intenta permitir que las implementaciones elijan entre muchas optimizaciones diferentes y competitivas. Sin embargo, dada la nota explícita, pensé que podría haber algunos concretos y, con suerte, algo más que "solicitó esta acción y estamos en desacuerdo, estado: rechazado". –

0

Si bien ya es especial, el vector < bool> tiene que asignarse en bloques de tamaño 8. También sé que algunas personas están trabajando para que malloc devuelva el "tamaño verdadero" de cualquier bloque asignado, por lo que si un bloque asignado habría introducido un desperdicio inevitable, en cambio el vector usa el espacio de manera útil. A medida que avanzamos a sistemas operativos de 64 bits, el espacio de memoria se vuelve repentinamente (famosas últimas palabras) más grande de lo que nadie pueda llenar, por lo que resulta mucho más razonable asignar grandes bloques de memoria virtual y llenarlos siempre. Mover objetos es caro, y en la práctica una pérdida de tiempo, ya que no estamos moviendo cosas porque la memoria física es limitada, ¡simplemente de un lugar virtual a otro!

+0

¿Cómo se relaciona esto con las posibles optimizaciones habilitadas por shrink_to_fit que no son vinculantes? –

+0

Porque si el vector se viera forzado a hacer shrink_to_fit, incluso cuando tuviera memoria extra de la que no podría deshacerse, terminaría reasignando, o simplemente "redescubriendo" esa memoria más adelante, al costo. Mejor que sea directo y decir "No puedo reducir mi memoria intermedia más pequeña que esta, sin desperdiciar memoria". –

Cuestiones relacionadas