Por lo que entendí el estándar (aunque en realidad no podría nombrar una referencia), la instanciación del contenedor y la asignación de memoria se han desacoplado intencionalmente por una buena razón. Por lo tanto, tiene llamadas distintas e independientes para
constructor para crear el propio contenedor
reserve() para preasignar un bloque de memoria suficientemente grande para acomodar al menos (!) un número determinado de objetos
Y esto tiene mucho sentido. El único derecho por el que existe reserve()es para darle la oportunidad de codificar en torno a reasignaciones posiblemente costosas al hacer crecer el vector. Para que sea útil, debe saber la cantidad de objetos que debe almacenar o, al menos, debe poder hacer una conjetura. Si no se le da esto, es mejor que se mantenga alejado, reserve()ya que solo cambiará la reasignación por memoria desperdiciada.
Así que poniendo todo junto:
- El estándar intencionalmente no especifica un constructor que le permita preasignar un bloque de memoria para un número específico de objetos (lo cual sería al menos más deseable que asignar un "algo" fijo y específico de implementación bajo el capó).
- La asignación no debe ser implícita. Entonces, para preasignar un bloque, necesita hacer una llamada separada a
reserve() y no es necesario que esté en el mismo lugar de construcción (por supuesto, podría / debería ser más tarde, después de que se dio cuenta del tamaño requerido para acomodar)
- Por lo tanto, si un vector siempre preasignaría un bloque de memoria de tamaño definido por la implementación, esto frustraría el trabajo previsto
reserve(), ¿no es así?
- ¿Cuál sería la ventaja de preasignar un bloque si el STL naturalmente no puede conocer el propósito previsto y el tamaño esperado de un vector? Será bastante absurdo, si no contraproducente.
- En cambio, la solución adecuada es asignar un bloque específico de implementación con el primero
push_back(), si no lo ha asignado explícitamentereserve() .
- En caso de una reasignación necesaria, el aumento en el tamaño del bloque también es específico de la implementación. Las implementaciones vectoriales que conozco comienzan con un aumento exponencial de tamaño, pero limitarán la tasa de incremento a un cierto máximo para evitar desperdiciar grandes cantidades de memoria o incluso arruinarla.
Todo esto llega a un funcionamiento completo y una ventaja solo si no lo perturba un constructor de asignación. Tiene valores predeterminados razonables para escenarios comunes que pueden ser anulados a pedido por reserve()(y shrink_to_fit()). Entonces, incluso si el estándar no lo dice explícitamente, estoy bastante seguro de que asumir que un vector recién construido no preasigna es una apuesta bastante segura para todas las implementaciones actuales.