Pregunta

string strLine;//not constant
int index = 0;
while(index < strLine.length()){//strLine is not modified};

cuántas veces se evalúa strLine.length()

¿necesitamos usar nLength con <=> asignado a <=> justo antes del bucle

¿Fue útil?

Solución

length se evaluará cada vez que pase por el bucle, sin embargo, dado que O(1) es tiempo constante (<=>) no hace mucha diferencia y agregar una variable para almacenar este valor probablemente tendrá un valor insignificante efecto con un pequeño golpe en la legibilidad del código (así como romper el código si la cadena se cambia alguna vez).

Otros consejos

length () se define en los encabezados que se incluyen en su archivo fuente, por lo que puede ser insertado por el compilador, sus llamadas internas también podrían estar integradas, por lo que si el compilador podría detectar que su instancia de cadena no ha cambiado en el bucle, entonces puede optimizar el acceso a la longitud de una cadena, por lo que se evaluará solo una vez. En cualquier caso, no creo que el valor de almacenamiento de la longitud de la cadena sea realmente necesario. Tal vez pueda ahorrarle algunos nanosecs, pero su código será más grande y habrá algún riesgo cuando decida cambiar esa cadena dentro del bucle.

Cada vez que se llama ... (cada uno durante la evaluación). Si no está cambiando la longitud de la cadena, está mejor con una variable temporal como:

string strLine;
int stringLength = strLine.length();
int index = 0;
while(index < stringLength);

Creo que hay una segunda pregunta al acecho dentro de esto, y esa es " ¿qué implementación es más clara? "

Si, semánticamente, quieres decir que la longitud de strLine nunca cambia dentro del cuerpo del bucle, hazlo obvio asignando una variable bien nombrada. Incluso lo haría constante. Esto deja en claro a otros programadores (y a usted mismo) que el valor de comparación nunca cambia.

La otra cosa que esto hace es que sea más fácil ver cuál es ese valor cuando estás revisando el código en un depurador. Hover-over funciona mucho mejor en un local que en una llamada de función.

Diciendo, " déjalo como una llamada de función; el compilador lo optimizará " me parece una pesimismo prematura. Aunque length () es O (1), si no está en línea (no puede garantizar que las optimizaciones no estén deshabilitadas), sigue siendo una llamada de función no trivial. Al usar una variable local, aclaras tu significado y obtienes una optimización de rendimiento posiblemente no trivial.

Haz lo que haga que tu intención sea más clara.

strLine.length () se evaluará mientras que (i < strLine.length ())

Dicho esto, si la cadena es constante, la mayoría de los compiladores optimizarán esto (con la configuración adecuada).

Si va a usar una variable temporal, use un calificador constante, para que el compilador pueda agregar optimizaciones sabiendo que el valor no cambiará:

string strLine;//not constant
int index = 0;
const int strLenght = strLine.Length();
while(index < strLine.length()){//strLine is not modified};

Lo más probable es que el compilador mismo realice esas optimizaciones al acceder al método Length () de todos modos.

Editar: mi ensamblaje está un poco oxidado, pero creo que la evaluación se realiza solo una vez. Dado este código:

int main()
{
    std::string strLine="hello world";

    for (int i=0; i < strLine.length(); ++i)
    {
        std::cout << strLine[i] <<std::endl;
    }
}

Genera este ensamblaje:

    for (int i=0; i < strLine.length(); ++i)
0040104A  cmp         dword ptr [esp+20h],esi 
0040104E  jbe         main+86h (401086h)

Pero para este código

 std::string strLine="hello world";
 const int strLength = strLine.length();
 for (int i=0; i < strLength ; ++i)
 {
    std::cout << strLine[i] <<std::endl;
 }

genera este:

   for (int i=0; i < strLength ; ++i)
0040104F  cmp         edi,esi 
00401051  jle         main+87h (401087h) 

Se genera el mismo ensamblaje si no se usa un calificador const, por lo que en este caso no hay diferencia.

Probado con VSC ++ 2005

Como se indicó, dado que la función string::length probablemente está completamente definida en un encabezado, y se requiere que sea O (1), es casi seguro evaluar a un simple acceso de miembro e integrarse en su código. Como no declara que la cadena es volátil, el compilador puede imaginar que ningún código externo lo va a cambiar, y optimiza la llamada a un único acceso a la memoria y deja el valor en un registro si encuentra que es un buena idea.

Al tomar y almacenar en caché el valor usted mismo, aumenta las posibilidades de que el compilador pueda hacer lo mismo. En muchos casos, el compilador ni siquiera generará el código para escribir la longitud de la cadena en la pila, y simplemente lo dejará en un registro. Por supuesto, si llama a diferentes funciones que el compilador no puede en línea, entonces el valor tendrá que escribirse en la pila para evitar que las llamadas de función alteren el registro.

Dado que no está cambiando la cadena, ¿no debería estar usando?

const string strLine;

Simplemente, porque entonces el compilador obtiene más información sobre qué puede y qué no puede cambiar; sin embargo, no estoy seguro de cuán inteligente puede ser un compilador de C ++.

strLine.length() se evaluará cada vez que recorra el ciclo.

Tienes razón en que sería más eficiente usar nLength, especialmente si strLine es largo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top