He estado haciendo algunas optimizaciones necesarias últimamente. Una cosa que he estado haciendo es cambiar algunos ostringstreams -> sprintfs. Estoy corriendo un montón de std :: strings a ac style array, ala
char foo[500];
sprintf(foo, "%s+%s", str1.c_str(), str2.c_str());
Resulta que la implementación std :: string :: c_str () de Microsoft se ejecuta en tiempo constante (solo devuelve un puntero interno). Parece que libstdc ++ hace lo mismo . Me doy cuenta de que el estándar no ofrece garantías para c_str, pero es difícil imaginar otra forma de hacerlo. Si, por ejemplo, copiaran en la memoria, tendrían que asignar memoria para un búfer (dejando que la persona que llama lo destruya, NO es parte del contrato STL) O tendrían que copiar a una estática interna buffer (probablemente no es seguro para subprocesos, y no tiene garantías de por vida). Entonces, simplemente devolver un puntero a una cadena terminada en nulo mantenida internamente parece ser la única solución realista.
fuente
c_str
es un método constante (o al menos tiene una sobrecarga constante, no recuerdo cuál), esto no cambia el valor lógico, por lo que puede ser una razónmutable
. Se podría romper punteros de otras llamadas ac_str
, salvo que cualquiera de estos indicadores deben referirse a la misma cadena lógica (lo que no hay nueva razón para reasignar - ya debe haber un terminador nulo) o de lo contrario debe haber sido una llamada a un no -const método en el medio.c_str
llamadas pueden ser O (n) tiempo para la reasignación y copia. Pero también es posible que haya reglas adicionales en el estándar que desconozco que evitarían esto. La razón por la que sugiero que - las llamadas ac_str
no son realmente destinado a ser común que yo sepa, por lo que no puede considerarse importante asegurarse de que están rápido - evitando que byte adicional de almacenamiento para un terminador nulo normalmente innecesario enstring
los casos que nunca se usoc_str
puede han tenido prioridad.Boost.Format
internamente pasa a través de corrientes que internamentesprintf
terminan con una sobrecarga bastante grande. La documentación dice que es aproximadamente 8 veces más lenta que la normalsprintf
. Si desea rendimiento y tipo de seguridad, intenteBoost.Spirit.Karma
.Boost.Spirit.Karma
es un buen consejo para el rendimiento, pero tenga en cuenta que tiene una metodología muy diferente que puede ser difícil de adaptar elprintf
código de estilo (y los codificadores) existentes. Me he quedado en gran parteBoost.Format
porque nuestra E / S es asíncrona; pero un factor importante es que puedo convencer a mis colegas para que lo usen de manera consistente (todavía permite cualquier tipo con unaostream<<
sobrecarga, lo que evita el.c_str()
debate) Los números de rendimiento de Karma .En el estándar c ++ 11 (estoy leyendo la versión N 3290), el capítulo 21.4.7.1 habla sobre el método c_str ():
const charT* c_str() const noexcept; const charT* data() const noexcept;
Entonces, sí: la complejidad del tiempo constante está garantizada por el estándar.
Acabo de comprobar c ++ 03 estándar, y no tiene tales requisitos, ni dice la complejidad.
fuente
En teoría, C ++ 03 no requiere eso y, por lo tanto, la cadena puede ser una matriz de caracteres donde se agrega la presencia del terminador nulo justo en el momento en que se llama c_str (). Esto puede requerir una reasignación (no viola la constancia, si el puntero privado interno se declara como
mutable
).C ++ 11 es más estricto: requiere una gran cantidad de tiempo, por lo que no se puede reubicar y la matriz siempre debe ser lo suficientemente amplia como para almacenar el valor nulo al final. c_str (), por sí mismo, todavía puede hacer "
ptr[size()]='\0'
" para asegurar que el nulo esté realmente presente. No viola la constancia de la matriz ya que el rango[0..size())
no cambia.fuente