Por ejemplo, suponiendo que un string s es este:

for(int x = 0; x < s.length(); x++)

mejor que esto?:

int length = s.length();
for(int x = 0; x < length; x++)

Gracias,
Joel

  • La primera consiste en la función de la sobrecarga de la llamada una vez para cada iteración del bucle, en lugar de sólo una vez. Hasta donde yo sé, el .length() método puede resultar en una no-trivial de cálculo (por ejemplo, un bucle por la cadena buscando un carácter de terminación), aunque esto es muy raro en el mundo real aplicación, AFAICT.
  • No estoy completamente seguro de que (como no estoy familiarizado con la aplicación de STL cadena), sin embargo, me parece que sería tomar la misma cantidad de tiempo excepto int length costaría sizeof(int) más memoria. Esto es suponiendo que s.length() simplemente devuelve un valor entero que se ha almacenado en la estructura.
  • Creo que .length está garantizada para ser O(1), desde std::string obedece a la Sequence requisitos.
  • Hice esta pregunta porque he leído en algún blog que ‘nunca se uso.longitud() en el condicional en un bucle porque tiene que buscar a través de la cadena para encontrar el terminador NULO de cada tiempo.’ Sólo quería saber si eso era correcto.
  • Eso sería cierto de strlen(), pero string.length() no puede ser implementado de la manera obvia el uso de un nul terminator desde std::string permite nul (cero) bytes a ser en la cadena.
  • El estándar de C++ no es garantía de que .length() constante de la complejidad; en el contenedor de requisitos (23.1) dice que ‘debe’ en lugar de ‘debe’, que permite un margen de maniobra. No creo que haya, en la práctica, cualquier corriente de implementaciones que han complejidad peor que lineal, sin embargo.
  • En C++0x n3225 (21.4.4), size() se garantiza que sea la constante de tiempo y length() se define como el rendimiento: size() sin esta garantía. No sé si quiere decir que es simplemente un alias, o si esto permite una mayor complejidad :/
  • Me refería a la versión de 2003 de la de 1998 estándar. Es bueno saber que esto ha sido reforzado en el próximo estándar.

InformationsquelleAutor Joel | 2011-02-27

6 Comentarios

  1. 14

    En general, se debe evitar las llamadas de función en la condición de parte de un bucle, si el resultado no cambia durante la iteración.

    La forma canónica es, por tanto:

    for (std::size_t x = 0, length = s.length(); x != length; ++x);

    Nota 3 cosas aquí:

    • La inicialización puede inicializar más de una variable
    • La condición se expresa con != en lugar de <
    • Yo uso pre-incremento, en lugar de post-incremento

    (También he cambiado el tipo porque es un negativo de la longitud no es el sentido y la cadena de interfaz se define en término de std::string::size_type, que normalmente es std::size_t en la mayoría de las implementaciones).

    Aunque… debo admitir que no es tanto por el rendimiento que para mejorar la legibilidad:

    • El doble de inicialización significa que ambos x y length alcance es tan apretado como sea necesario
    • Por memorización el resultado de que el lector no se quede en la duda de si es o no la longitud puede variar durante la iteración
    • El uso de pre-incremento es generalmente mejor cuando usted no necesita crear un temporal con el «viejo» valor

    En resumen: el uso de la mejor herramienta para el trabajo en la mano 🙂

    • Y (4), length devuelve un size_t.
  2. 5

    Depende de las alineaciones y optimización de las capacidades del compilador. En general, la segunda variante más probable es que sea más rápido (mejor: va a ser más rápido o tan rápido como el primer fragmento, pero casi nunca más lento).

    Sin embargo, en la mayoría de los casos no importa, así que las personas tienden a preferir la primera variante de su falta.

  3. 4

    Depende de su implementación en C++ /biblioteca, la única manera de estar seguro es punto de referencia que. Sin embargo, es cierto que la segunda versión nunca será más lento que el primero, así que si usted no modificar la cadena de dentro del bucle es una sensata la optimización de hacer.

  4. 1

    De lo eficiente que quieres ser?

    Si no modificar la cadena de dentro del bucle, el compilador puede ver que el tamaño no cambia. No hacerlo más complicado de lo que te han a!

  5. 1

    Aunque no estoy necesariamente animan a hacerlo, parece que es más rápido a la constante llamada .length() que guardarla en un int, sorprendentemente (al menos en mi equipo, teniendo en cuenta que estoy usando una MSI gaming portátil con core i5 4ª gen, pero no debe afectar la manera más rápida).

    Código de prueba para la llamada constante:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        string g = "01234567890";
        for(unsigned int rep = 0; rep < 25; rep++)
        {
            g += g;
        }//for loop used to double the length 25 times.
        int a = 0;
        //int b = g.length();
        for(unsigned int rep = 0; rep < g.length(); rep++)
        {
            a++;
        }
        return a;
    }

    En promedio, esta corrió para 385ms de acuerdo con Code::Blocks

    Y aquí está el código que almacena la longitud de una variable:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        string g = "01234567890";
        for(unsigned int rep = 0; rep < 25; rep++)
        {
            g += g;
        }//for loop used to double the length 25 times.
        int a = 0;
        int b = g.length();
        for(unsigned int rep = 0; rep < b; rep++)
        {
            a++;
        }
        return a;
    }

    Y este promedio de alrededor de 420ms.

    Sé que esta pregunta ya ha aceptado la respuesta, pero no ha habido ninguna prueba en la práctica las respuestas, así que me decidí a lanzar mis 2 centavos. Yo tenía la misma pregunta que tú, pero no encontré respuestas útiles aquí, así que me fui corriendo a mi propio experimento.

  6. 0

    Es s.longitud() inline y devuelve una variable de miembro? entonces no, de lo contrario el costo de la eliminación de referencias y poniendo cosas en la pila, usted sabe todos los gastos generales de la función que se incurre por cada iteración.

Dejar respuesta

Please enter your comment!
Please enter your name here