2009-08-26 10 views
7

Dos preguntas rodaron en una aquí ...C++ y QT4.5 - ¿está pasando un const int y overkill? ¿Pasa por referencia ayuda en señales/ranuras?

Tengo una serie de funciones que se llaman varias veces por cuadro para una aplicación de procesamiento de video en tiempo real. Tomando consejos sobre const y pasar por referencia, las funciones tienen una firma algo como esto

void processSomething(const int& value); 

Como sigo escribiendo los pocos caracteres adicionales, me pregunto si esto es una exageración.

La segunda pregunta, bueno, sobre el tema de pasar por referencia, dentro del mecanismo de ranuras/señales de QT, ¿pasa por referencia ayuda a prevenir la copia de objetos como en una llamada a función normal?

+6

Todos los consejos sobre const y pass por referencia que he leído siempre incluyen la condición "excepto para los tipos incorporados". –

Respuesta

19

Sí, esto es exagerado y en realidad dará como resultado código más lento que si pasó el int por valor. Un int es cuatro bytes; una referencia (esencialmente una dirección de memoria) también es cuatro bytes (en una máquina de 32 bits) u ocho bytes (en una máquina de 64 bits). Por lo tanto, es posible que necesite pasar más información de a la función y, además, tiene la ventaja de desreferenciar esa referencia.

Si está pasando algo más grande que un int, sin embargo, es más eficiente usar una referencia constante, ya que puede pasar solo cuatro u ocho bytes en lugar de tener que copiar el objeto completo.

Editar En cuanto a Qt: Sí, si la ranura toma una referencia directa a un objeto, entonces la razón es que se ahorra la sobrecarga de copiar el objeto.

7

Sí, pasar por referencia ayuda a evitar la copia de los objetos. Pero el compilador podría decidir optimizarlo por completo e insensuar pasar por valor si produce el mismo efecto. Dicha optimización suele ser posible si la función y el sitio de llamada se encuentran en la misma unidad de traducción, pero algunos compiladores pueden realizar optimizaciones aún más globales: si lo desea, puede inspeccionar el conjunto emitido.

Es por esto que realmente no debe pasar tipos primitivos por referencia si le importa el rendimiento y a menos que realmente tenga motivos para eso. Ver What is the use of passing const references to primitive types? para la discusión de ese problema.

+1

La única situación en la que el compilador podría hacer esta optimización, sin embargo, es si la persona que llama y quien llama están en la misma unidad de traducción. –

+1

En realidad, no, y Visual C++ lo demuestra. Lo llaman Generación de código de tiempo de enlace. ISO C++ no especifica las responsabilidades exactas del preprocesador, compilador, enlazador y tiempo de ejecución. – MSalters

4

primer lugar - la diferencia entre

  • processSomething vacío (const int valor &);
  • void processAlgo (valor int);

es: normalmente una referencia de const se pasa pasando un puntero, la otra cosa se pasa mediante copia. Después de la llamada (del lado del que llama) el resultado es igual. Lo que pase a la función no cambia con la llamada.

Dentro de la función, tampoco verá ninguna diferencia (al menos en un int). En Objetos, solo puedes usar funciones const por supuesto.

Por el lado del rendimiento: pasar una referencia constante a un int puede (o no) ser más lento, según el compilador y la optimización. El compilador podría (en teoría) optimizar el paso de la referencia constante a un valor de pase, aunque no sé si lo hará. Trabajar con punteros a enteros en lugar de valores es más lento, por supuesto.

Para obtener más información sobre que ver: When to use pointers, and when not to use them


Después de leer el otro post relacionado - el compilador no puede optimizar la basura en un entorno multiproceso. Al menos en un entorno MT existen diferencias reales entre const int & y llamadas int. +1 para ese enlace.

+0

En realidad, tampoco puede usar funciones no const en 'const int & value'. Es decir, si tengo 'void foo (int &)', entonces 'processSomething (const int & value) {foo (value); } 'es ilegal pero' processSomething (int value) {foo (value); } 'es legal. – MSalters

Cuestiones relacionadas