2012-08-13 14 views
12

En un entorno práctico, usando gcc o MS Visual Studio, ¿es malo pasar los tipos de valor que son del mismo tamaño o menos que un int por referencia de referencia?En C++, ¿es malo pasar un const bool por referencia?

es decir, ¿es malo para escribir una función de este tipo:

void f(const bool& b); 

o

void f(const char& c); 

en lugar de:

void f(bool b); 

o

void f(char c); 

La razón por la que estoy preguntando es que no veo el beneficio de pasar una referencia en estos casos, pero tal vez me falta algo.

+2

Como la mayoría de la gente ha dicho, en realidad no tiene sentido, ya que pasar estos por valor probablemente será más rápido. Sin embargo, recuerde que escribir código de limpieza viene antes de estas pequeñas optimizaciones, y en ocasiones puede tener varias funciones muy similares que toman argumentos por referencia constante, y luego quiere que las versiones 'bool' y' char' se vean consistentes. Un punto sin importancia, pero quizás vale la pena considerarlo, para que la gente no lo vea pensando "¿por qué esta es diferente?" – BoBTFish

Respuesta

15

Puede ser un poco malo, o puede no tener ningún efecto (depende de dónde está almacenado el valor original, cuán bueno es el optimizador y cómo decide tratar tu código).

La norma no ordena cómo se implementarán las referencias, pero en la práctica los compiladores implementan referencias utilizando punteros. Por lo tanto, en el caso general, se implementaría un bool& usando un bool*, lo que significa que para acceder al bool necesita una desreferencia de puntero adicional cada vez. Como un bool no es más grande que un puntero, no hay espacio de memoria reducido o menos copiado de bytes para compensar este inconveniente.

Como resultado, la práctica aceptada es pasar las primitivas como valores ya que es más eficiente. Por supuesto, aunque pasar tales referencias no va a explotar nada, y a menos que esté accediendo al valor dentro de un bucle, probablemente no resultará en ninguna diferencia apreciable.

+0

Cuando escribe "Como un bool no es más grande que un puntero, no hay huella de memoria reducida o menos copia de bytes para compensar este inconveniente". En realidad, un bool ocupa menos espacio que un puntero en la práctica, dependiendo de si pasa varios bools como argumentos, lo que lleva a la memoria más utilizada al pasar por referencia o es un bool tomando el mismo espacio que un int como argumento de una función? – BlueTrin

+0

El único caso en el que probablemente encontrará tipos primitivos pasados ​​por referencia (es decir, 'bool const &') está en instancias de plantilla. A menos que se especialice explícitamente para todos los tipos primitivos, los tipos primitivos y los tipos más complejos usarán la misma firma. –

+4

@BlueTrin: cuánto espacio se ocupa depende de los valores de 'sizeof (bool)' y 'sizeof (bool *)' en su arquitectura. Pasar múltiplos de cada parámetro no cambia la imagen. – Jon

-1

Realmente no importa, pasar de valor hace que el código sea más limpio y, por lo tanto, se considera una buena práctica.

1

Creo que es mejor pasar los tipos integrados by value en lugar de const reference ya que es prácticamente más rápido. En caso de pasar por referencia, necesita crear una referencia (es decir, tomar una dirección) y luego eliminar la referencia cuando usa la variable. En la mayoría de los casos será optimizado por el compilador en cualquier caso, aunque

+1

Solo se puede optimizar si la función está en línea. Si considera * funciones * en línea * la mayoría de los casos * o no es una pregunta diferente. –

2

Una razón sería que le gustaría transmitir a otros programadores que el valor es constante, en algunos casos puede ser más claro aunque const bool sería suficiente.

+2

Al pasar por valor, queda aún más claro que la función no modificará el valor de la persona que llama. –

+0

Pasar por const-reference no transmite el significado de que la fuente es constante, solo que no será modificada por la función (ver la respuesta de Björn: el código fuera de la función aún puede cambiar el valor). Además, 'const bool' como argumento no transmite ninguna información, ya que en una declaración de función, el cv-qualifier superior se descarta (es decir,' void f (bool); 'y' void f (const bool) 'son exactamente la misma declaración de función. –

0

Aunque en teoría no será una buena idea, ya que las referencias generalmente se implementan usando punteros. Sin embargo, todos los compiladores razonables deberían ser lo suficientemente inteligentes como para reconocer la indiferencia en semántica entre by-const-reference y by-value para los tipos fundamentales.

A menudo no tiene elección si tiene algún tipo de interfaz con plantilla que tiene que funcionar para tipos complejos y tipos fundamentales y no desea excesiva sobrecarga de especialización (el ejemplo más simple es std::vector). Pero si tiene una opción, entonces se debe preferir pasar los tipos fundamentales por valor.

11

Rendimiento a un lado, en realidad hay casos en los que obtendrá un comportamiento diferente.

Por ejemplo, al pasar una referencia const, se asegura de que la función no puede cambiar el valor de la variable referenciada, pero puede hacerlo otro subproceso. Si pasa por referencia (incluso con const), verá estos cambios, si pasa por valor, no lo hará.

Además, la definición de la interfaz limita lo que puede hacer con la variable dentro de la función. Considere este ejemplo:

int foo(int a) { 
    a = 5; // valid 
} 

int bar(const int& a) { 
    a = 5; // compiler-error 
} 

Si pasa por referencia, y desea modificar el valor de la variable para uso local, es necesario hacer una copia adicional. Si pasa por valor, ya tiene una copia.

+0

Muy buen punto acerca de un entorno multiproceso – BlueTrin

+4

Tenga en cuenta que no necesita varios subprocesos para cambiar la variable referenciada. Podría tener (por ejemplo) 'bool b (falso); void f (const bool & a) {assert (! a); b = verdadero; assert (a);} int main() {f (b);} '. – Mankarse

+1

+1 Por mencionar posibles cambios al argumento en diferentes lugares (a través de otras referencias). También significa que debido a un posible problema de aliasing, no se realizarán algunas optimizaciones. –

Cuestiones relacionadas