En C++11, me pueden recorrer algunos de contenedores así:

for(auto i : vec){
   std::cout << i << std::endl;
}

Pero yo sé que este innecesariamente – innecesariamente, puesto que sólo se necesita para de impresión los valores de vec – hace una copia de (EDITAR: cada elemento de) vec, así que en lugar que podía hacer:

for(auto &i : vec){
   std::cout << i << std::endl;
}

Pero quiero asegurarme de que los valores de vec nunca son modificados y acatar const-corrección, así que puedo hacer:

for(const auto &i : vec){
   std::cout << i << std::endl;
}

Así que mi pregunta es: Si solo necesito mirada en los valores de algunos contenedor, ¿no sería el último bucle (const auto &i) siempre será la preferida por la mayor effieciency de no tener una copia adicional de (EDITAR: cada elemento de) vec?

Tengo un programa que estoy desarrollando en el que estoy considerando la posibilidad de hacer este cambio en todo, ya que la eficiencia es fundamental en ella (la razón por la que estoy usando C++ en el lugar del puño).

  • Sí, si usted sólo necesita acceso de lectura a un argumento, debe ser a través de auto const& para evitar una innecesaria copia.
  • La «const» la palabra clave no es hacer el código más rápido, aunque…
  • for (auto i : vec) no hacer una copia adicional de la totalidad de la vec, se copia a cada elemento de vec en i.
  • Lo que yo veo. De modo que, en cada nueva iteración, la copia anterior es eliminado, ¿verdad?
  • Sí, eso es correcto.
  • no se elimina, sino que se destruye.

InformationsquelleAutor user2052561 | 2013-06-10

3 Comentarios

  1. 70

    Sí. La misma razón, si usted sólo he leído un argumento que hacer el parámetro const&.

    T        //I'm copying this
    T&       //I'm modifying this
    const T& //I'm reading this

    Esos son sus «valores predeterminados». Cuando T es un tipo fundamental (built-in), aunque, en general, sólo volver a const T (sin referencia) para la lectura, ya que una copia es más barato que el aliasing.


    Tengo un programa que estoy desarrollando en el que estoy considerando la posibilidad de hacer este cambio en todo, ya que la eficiencia es fundamental en

    1. No hacen ciegos cambios radicales. Un programa de trabajo es mejor que una rápida pero roto programa.
    2. Cómo iterar a través de los bucles probablemente no hará mucha diferencia; usted está en busca de una razón, ¿no? El cuerpo del bucle será mucho más probable que sea el culpable.
    3. Si la eficiencia es fundamental, desea utilizar un analizador de a encontrar las partes de su programa son en realidad lento, en lugar de adivinar las partes que podría ser lento. Ver #2 por qué su conjetura que puede ser incorrecta.
    • «copia es más barato que el aliasing» sólo con la mayoría de los tipos fundamentales, además de mover semántica no ha sido utilizado en el OP de la situación y desde que T puede ser de cualquier tipo, una referencia sería la elección correcta.
    • ««copiar es más barato que el aliasing» sólo con la mayoría de los tipos fundamentales«, Que es la razón por la que la primera mitad de la frase se dedica a decir que se aplica a los tipos fundamentales…? Obviamente, si usted no sabe el tipo, utilice el caso general.
    • Me disculpan, debo haber leído sobre él.
    • No se preocupe, es bueno mencionar el caso general, cuando el tipo no pueden ser fácilmente reconocidos.
    • ¿Por qué el compilador genere código diferente para, por ejemplo, «int» y «const int &» en un rango de bucle ? Se hace una diferencia al pasar argumentos a una función, pero en un rango de bucle el compilador tiene todo lo que necesita para optimizar el infierno fuera de él. He intentado desmontar un par de rango-bucles y el código generado es el mismo. Mismo para estructuras con trivial dtor y trivial copia-cto r.
    • Que no, que por qué deberíamos utilizar const T&. En general, este lo que quiere, y es inútil esfuerzo para modificar aún más a «const T» o simplemente «T» cuando por casualidad usted conoce T; el compilador hará este derecho para usted.
    • con const auto& que la señal de su intención de no modificar nada y que no se necesita una copia. Incluso si el rendimiento era el mismo, me gustaría ir con eso, porque no hace que el código sea más expresivo.

  2. 1

    Imaginar si el vector contiene cadenas. De cadenas largas. 5000 de cadenas largas. Copia innecesariamente, y usted termina con un muy bien escrito bucle for que es terriblemente ineficiente.

    Asegúrese de que el código de la siguiente manera su intención. Si usted no necesita una copia dentro del bucle, no hacer uno.

    Utilizar una referencia & como se sugirió anteriormente, o de los iteradores.

  3. 1

    Descargo de responsabilidad: En general la diferencia entre auto y auto& es sutil, en parte, una cuestión de estilo, pero a veces también una cuestión de corrección. No voy a cubrir el caso general aquí!

    En una amplia base de bucle, la diferencia entre

    for (auto element : container) {}

    y

    for (auto& element_ref : container) {}

    es que element es una copia de los elementos en la container, mientras que element_ref es una referencia a los elementos en el contenedor.

    Para ver la diferencia en la acción, considere este ejemplo:

    #include <iostream>
    
    int main(void) {
        int a[5] = { 23,443,16,49,66 };
    
        for (auto i : a) i = 5;       
        for (const auto& i : a) std::cout << i << std::endl;
        for (auto& i : a) i = 5;   
        for (const auto& i : a) std::cout << i << std::endl;    
    }

    Se va a imprimir

    23
    443
    16
    49
    66
    5
    5
    5
    5
    5

    porque el primer bucle de obras en las copias de los elementos de la matriz, mientras que el segundo modifica los elementos de la matriz.

    Si usted no desea modificar los elementos, a continuación, a menudo un const auto& es la más apropiada, debido a que se evita la copia de los elementos (que pueden ser costosos).

    • tenía esta respuesta por escrito para otra pregunta que tengo cerrado como engañar, no quería a la basura, espero que también encaja aquí….

Dejar respuesta

Please enter your comment!
Please enter your name here