2009-09-18 13 views
19

¿Qué es mejor:¿Debo devolver bool o const bool?

bool MyClass::someQuery() const; 

const bool MyClass::someQuery() const; 

He estado usando 'bool const' ya que estoy seguro Recuerdo haber oído que es "lo que los enteros hacen" (por ejemplo, para los operadores de comparación), pero no puedo encontrar pruebas de eso en cualquier lugar, principalmente debido a que es difícil para Google e Intellisense no ayudar a ninguno;) ¿Alguien puede confirmar eso?

Para mí, devolver los valores de const (esto no se trata solo de bools) tiene más sentido; evitará que se modifiquen los temporales, lo que casi siempre será un error del programador. Solo quiero que algo respalde eso para poder exaltar el retorno de los valores de const a mis colegas :)

+2

¿Cuál es el problema al permitir modificar los temporales? Puede ser una optimización importante (el compilador puede reutilizar su temporal en lugar de copiar en un nuevo no const). Es * no * "casi siempre un error del programador" – jalf

+2

Creo que el ejemplo en C++ efectivo es bueno; "if ((a * b) = c)" probablemente sea un error y se detectará haciendo que el operador * devuelva un valor constante. Algo como "normalizar (crossProduct (a, b))" es otro, si normalize modifica su entrada en lugar de devolver una copia modificada, lo que hace que crossProduct devuelva un valor const que capte esto. –

+0

@Ben: si normalize() modifica su entrada, entonces es una (T x) y por eso una variable local. En ese caso, es libre de modificarlo, pero nunca será "devuelto" (porque es local para normalizar). Si es un (T & x), entonces no puede llamarlo de esa manera porque no puede pasar valores r como referencias no const! Por lo tanto, debe declarar la normalización como T normalizar (T x) o T normalizar (const T & x) para llamarlo de la manera en que lo hizo. De lo contrario, el compilador se quejaría. – mmmmmmmm

Respuesta

23

¿Así que sabes que es correcto, estás justo detrás de la Voz de la Autoridad? La prevención de modificaciones accidentales de temporales es muy valiosa. En general, debe declarar tantas cosas como sea posible const, lo protege de una variedad de accidentes y le da al optimizador consejos útiles.

¿Tienes una copia de "Effective C++" de Scott Meyers? Punto ellos en el punto 3 (página 18 en la tercera edición);)

Se da el ejemplo de

class Rational {...}; 
const Rational operator* (const Rational& lhs, const Rational& rhs); 

if((a * b) = c) // declaring operator *'s return value const causes error to be caught by compiler 
+2

No tengo idea de por qué se votó negativamente, ¡es exactamente la respuesta que estaba buscando! Gracias :) No es que agregue ninguna otra respuesta, por supuesto; También pregunté "qué es mejor", por lo que las opiniones sobre la complejidad añadida y demás también son bienvenidas. –

+8

Esto no tiene nada que ver con su pregunta. Se preguntó si tenía sentido hacer un const * * bool * return value. Y respondes con un tipo complejo que no sea POD. -1 – jalf

+9

@Ben: Fue rechazado porque no tiene nada que ver con su pregunta. Para un bool u otros tipos incorporados, const devolviendo hace cero diferencia, y este ejemplo no se habría compilado de todos modos. – jalf

13

Cuando devuelve una referencia a una variable miembro, tiene sentido hacerlo const. Aquí está devolviendo una copia, por lo tanto, no hay necesidad de const.

2

No importa por completo. Por lo tanto, el consenso es devolver solo bool.

La razón por la que no importa es que no puede llamar a las funciones de miembros no const de ninguna manera; bool no es una clase o estructura.

1

const return type

RESUMEN:

El valor de un tipo de retorno eso es declarado const no puede ser cambiado. Este es especialmente útil cuando se da una referencia a las partes internas de una clase, pero también puede evitar errores más raros.

29

Este es el caso cuando const no agrega ningún valor pero infla el código y hace que el lector piense más. ¿Cuál es el objetivo de este const? El que llama puede copiar el valor en alguna variable no const y hacer lo que quiera con ella de todos modos.

7

El modificador const sólo se usa para tipos de retorno que se devuelven por referencia (ya sea como referencia const SomeObject& o por medio de un puntero const SomeObject*), por lo que la persona que llama no será capaz de modificar el objeto a través de la referencia/puntero. Los tipos primitivos se devuelven por el valor, lo que significa que la persona que llama recibe una copia del objeto, no el objeto en sí.

Por lo tanto, const no es realmente apropiado para los tipos de valores devueltos. Como la copia está fuera del control de la función llamada, la función llamada no debe dictar a la persona que llama que no se puede cambiar.

19

Tenga en cuenta que if((a*b) = c) no compilará para tipos incorporados de todos modos, por lo que es muy relevante aquí si estamos hablando de tipos incorporados (su pregunta es bool) o tipos definidos por el usuario.

Para los tipos incorporados no tiene ningún sentido, por lo que no debe usarse. Y para los tipos definidos por el usuario, estoy en el campo de jalf: ¿Qué pasa si la persona que llama quiere para modificar el objeto devuelto?

no estoy convencido de que if((a*b) = c) es un buen argumento para el retorno de los tipos definidos por el usuario const, ya que no puedo recordar la última vez que he visto un compilador no advierten sobre esto.

+0

Ok, pero falla por otros motivos. El ejemplo de normalizar (crossProduct (a, b)) probablemente sea mejor allí, aunque el ejemplo que realicé en el teclado falla porque supongo que está basado en gcc, que no permite el enlace de temporarios a referencias no const ... en MSVC debería tener éxito, en contra de la intención del programador. –

+4

@Ben: MS llama a la capacidad de su compilador para vincular temporalmente a las referencias no const una "característica", poco es, de hecho, un error. – sbi

+0

Vea mi comentario sobre la pregunta sobre la normalización (...) "ejemplo". ¡Incluso no mencioné la cosa de MS "no es un error, es una característica" sobre los valores de enlace a las referencias no-const! – mmmmmmmm

0
const bool func(); 
bool f = func(); 

0 errores, 0 advertidos. ¿Qué has logrado aparte de la inflación innecesaria del código?

+0

Eso es está bien, la copia es explícita y cualquier modificación será explícita. No logra nada en esa circunstancia, es más para evitar modificaciones accidentales de los temporales, donde la modificación se perderá al final de la declaración. –

2

Como bool se va a copiar, es lo mismo, poner const o no. Además, es posible que tengas algunos problemas de compilación.

15

Para ser un poco más específico, solo los "objetos" pueden ser const. La definición de "objeto" del estándar C++ incluye todo lo que se refiere a un lvalue ("tiene un nombre") y los temporales de clase. Un valor de retorno booleano es un valor r de un tipo que no es de clase, por lo que un compilador que cumpla con los estándares simplemente ignorará "const" en este caso. Como otros ya dijeron, es inútil en este contexto.

+0

Gracias para obtener detalles adicionales, ¿significa esto que * sería * útil para los tipos de clase? –

+6

Sí. Algunas personas prefieren devolver objetos const para evitar asignaciones. Esto generalmente está motivado por un posible error tipográfico if (get_object() = blah) ... que no se compilará si la función get_object() devuelve un objeto const (de algún tipo de clase). Pero nunca consideré que esto sea un gran problema. A la luz de C++ 0x, las referencias rvalue y semánticas de movimiento que devuelven objetos const pueden ser contraproducentes y disminuir el rendimiento.C++ 0x ofrece una mejor solución para evitar asignaciones en objetos rvalue: ref calificadores. – sellibitze

+0

Excelente respuesta. Ojalá pudiera votar esto dos veces. –

0

Esta es una publicación antigua, pero creo que vale la pena mencionar que existe un posible caso de esquina aquí desde C++ 11. Mientras que, según lo manifestado por otros, no importará si usa const bool o bool como tipo de devolución en la mayoría de los casos, si está usando C++ 11 decltype y asociados, p. result_of, podría declarar una variable con el mismo tipo que el valor de retorno de alguna función, por lo que el const tendría un efecto en este caso.