2012-02-25 17 views
5

Digamos que quiero iterar a través de una matriz de dobles y sumarlos. Tengo dos formas de hacer esto.punteros de matriz C++ [] o ++

A)

double sum (double * series, int size) { 
    double sum = 0.0; 
    for (int i = 0; i < size; i++) { 
     sum += *series++; 
    } 
    return sum; 
} 

B)

double sum (double * series, int size) { 
    double sum = 0.0; 
    for (int i = 0; i < size; i++) { 
     sum += series[i]; 
    } 
    return sum; 
} 

que es mejor y por qué/cuando debería utilizar uno sobre el otro.

+0

Me gusta B) porque es más corto y más fácil de entender si no sabes cómo funcionan los punteros. Puedes usar vectores con std :: accumulate también. – chris

+0

El estilo A no es tan claro para mí en lo que está logrando. Personalmente, siempre elijo el estilo B, que proviene de un fondo de C#. –

+0

@Richard J. Ross III, '* series' evalúa los datos contenidos en a qué series apunta. El ciclo incrementa la serie, por lo que apunta al siguiente elemento de la matriz cada vez. – chris

Respuesta

6

Esta es una cuestión de legibilidad, no debe afectar el rendimiento. Creo que B es el más legible y, por lo tanto, preferible.

También podría proponer una tercera variante, que es basada en la gama (cuenta los parámetros begin y end):

double sum (double* begin, double* end) { 
    double sum = 0.; 
    for (double* it = begin; it != end; ++it) { 
     sum += *it; 
    } 
    return sum; 
} 

Esto es C idiomática ++ en muchos casos y generaliza más fácilmente. Eso no quiere decir que sea siempre preferible, es solo otra variante en una pregunta sobre legibilidad y mantenibilidad.

+0

Sí, esto es básicamente lo que std :: accumulate hace con los vectores. – chris

+0

Esperemos que 'begin'' <'' end'. ¿Qué sucede si 'begin'' == '' end'? –

+1

@SimonWright: Entonces no ingresará al bucle, y devolverá 0 de inmediato. La condición de bucle se verifica antes de ingresar al cuerpo :) –

4

Ninguno es intrínsecamente mejor que el otro; debe elegir el que más clara sea la intención de su código. Con cualquier compilador moderno, deberían optimizarse para un código de máquina idéntico.


Tenga en cuenta, sin embargo, que pasa alrededor de punteros primas a las matrices primas se considera mal estilo en C++. Considere usar una clase de contenedor como std::vector.

1

En términos de rendimiento, no debería haber ninguna diferencia cuando utiliza compilaciones optimizadoras modernas.

En 1978, la primera manera era algo más rápida en PDP-11, porque el direccionamiento indirecto de autoincremento requería menos ciclos para procesar, y no había optimizadores capaces de convertir index + offset a autoincrement.

P.S. La configuración series -= size; no tiene ningún efecto, porque series se pasa por valor.

+0

series - = tamaño; establece la serie para señalar el primer elemento, ¿verdad? –

+1

@PatrickLorio Sí, pero lo hace en la * copia * del puntero, que se pasa por valor. Como regresas a la siguiente línea sin acceder a 'series' después de la asignación, esta asignación no tiene efecto. Tendría sentido si usara ese puntero * nuevamente *, por ejemplo para encontrar el elemento más grande o más pequeño además de encontrar la suma. – dasblinkenlight

+3

@PatrickLorio No importa. Debido a que el puntero real pasado se pasa por valor, cuando '- =' el tamaño no afecta a la variable que se pasó inicialmente. –

5

volvería a elegir el estilo B también, pero entonces usted debe preferir algoritmos estándar sobre bucles explícitas:

#include <numeric> 

double sum(const double* const series, const int size) { 
    return std::accumulate(series, series + size, 0.0); 
} 
0

El C++ 11 camino a recorrer la matriz (si no desea apenas suma ellos y que se acumulan no se ajusta a sus necesidades) es:

double sum (const double * series, int size) { 
    double sum = 0.0; 
    for_each (series, series + size, [&](double v) { 
     sum += v; 
    }); 
    return sum; 
} 

Tenga en cuenta que si se ha utilizado un vector o una lista que te dan más o menos el mismo código:

double sum (const vector<double>& series) { 
    double sum = 0.0; 
    for_each (begin(series), end(series), [&](double v) { 
     sum += v; 
    }); 
    return sum; 
}