2011-01-21 6 views
42

¿Hay alguna diferencia entre estas dos instrucciones dentro de una función?¿Los paréntesis alrededor del resultado son significativos en una declaración de devolución?

bool returnValue = true; 

//Code that does something 

return(returnValue); 

y esto?

bool returnValue = true; 

//Code 

return returnValue; 

La primera tiene paréntesis alrededor de returnValue.

+10

Prepárese para algunas insignias. Curiosamente, estas preguntas * siempre * obtienen la mayor cantidad de visitas. –

+2

Bienvenido a Stack Overflow, Jose. Por favor, tome nota de la edición que hice a su pregunta. Menciona específicamente el cambio entre los dos bloques de código, lo que ahorra a los lectores la frustración de tener que jugar [detectar la diferencia] (http://www.spotthedifference.com/) con su código. También ayuda a las personas a reconocer cuándo una diferencia fue intencional en lugar de un simple error tipográfico (como 'boo'). –

+0

Gracias Rob, has capturado con éxito el espíritu de la pregunta. En Essence me preguntaba si el compilador hizo algo especial (como tratar de evaluar la expresión primero) o si simplemente lo ignoró. –

Respuesta

63

C++ 14 añade una franja caso donde los paréntesis alrededor de un valor de retorno pueden alterar la semántica. Este fragmento de código muestra dos funciones que se declaran. La única diferencia es paréntesis alrededor del valor de retorno.

int var1 = 42; 
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1) 
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1)) 

En los primeros func1 devuelve un int y en el segundo func1 devuelve un int&. La diferencia en semántica está directamente relacionada con el paréntesis circundante.

El especificador auto en su última forma se introdujo en C++ 11. En el C++ Language Spec se describe como:

especifica que el tipo de la variable que se está declarada será automáticamente deduce de su inicializador. Para las funciones, especifica que el tipo de retorno es un trailing tipo retorno o se deduce de sus estados de retorno (desde C++ 14)

Como bien C++ 11 introducido el especificador decltype que se describe en el C++ Language Spec:

Inspecciona el tipo de declaración de una entidad o pregunta el tipo de devolución de una expresión.

[snip]

  1. Si el argumento es el nombre unparenthesised de un objeto/función, o es una expresión del acceso de miembros (object.member Puntero-> miembro o), entonces el decltype especifica el tipo declarado de la entidad especificada por esta expresión.

  2. Si el argumento es cualquier otra expresión de tipo T, entonces

    a) si la categoría valor de la expresión es xValue, entonces el decltype especifica T & &

    b) si la categoría valor de expresión se lvalue, entonces el decltype especifica T &

    c) en caso contrario, decltype especifica T

[snip]

Tenga en cuenta que si el nombre de un objeto se parenthesised, se convierte en una expresión valor-I, por lo tanto decltype (arg) y decltype ((arg)) a ​​menudo son diferentes tipos.

En C++ 14 la capacidad de utilizar decltype(auto) se dejó para este tipo de retorno de la función. Los ejemplos originales son donde entra en juego la diferencia semántica con paréntesis. Revisando los ejemplos originales:

int var1 = 42; 
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1) 
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1)) 

decltype(auto) permite el tipo de retorno final en la función que se deduce de la entidad/expresión en la instrucción de retorno. En la primera versión return var1; es efectivamente lo mismo que devolver el tipo decltype(var1) (un int tipo de devolución según la regla 1 anterior) y en el segundo caso return (var1); es efectivamente el mismo que decltype((var1)) (un tipo de devolución int & según la regla 2b).

Los paréntesis hacen el tipo de retorno int& en lugar de int, por lo tanto, un cambio en la semántica. Moraleja de la historia: "No todos los paréntesis en un tipo de devolución se crean iguales"

+0

La declaración de devolución sin paréntesis sigue siendo una expresión lvalue, ¿verdad? A menos que se trate como un xvalor en ese escenario. ¿Puedes explicar la categoría de valor de la declaración sin paréntesis? –

+0

La declaración return devuelve una lectura de la expresión introducida en ella, es decir, captura un valor r de la expresión que contiene y lo devuelve. Nunca devolvemos un lvalue Es posible que algún compilador tenga un error que coincida con la descripción que usted brinda aquí, y por las razones que usted brinda aquí, pero nunca debería darse el caso de que 'return (x);' sea equivalente a 'return & x;', ni debería ser posible que resulte en un retorno del valor de x pero con el tipo referencia a x. –

11

Sí, uno vuelve un bool, mientras que el otro un boo ...


Después de la edición:

no, son lo mismo.

+1

Eso es un error tipográfico, creo. –

+0

Gracias por señalar eso. –

+0

+1 para respuesta divertida editada por respuesta;) – BlackBear

0

No hay diferencia!

Las personas usan paréntesis si se trata de una expresión compleja.

BTW return es una afirmación que no es una función.

+0

Más como personas usan paréntesis si son novatos para C .. –

5

No hay diferencia.

Una razón para usar paréntesis sería si quisiera evaluar una expresión antes de regresar pero en su ejemplo, no habría ninguna razón. Ver:

Parenthesis surrounding return values

para continuar el debate.

+2

Aunque incluso con una expresión complicada, estos paréntesis todavía no causan un comportamiento diferente. Simplemente hacen que el significado sea más obvio (¡subjetivamente!) Para los lectores humanos. – aschepler

+0

@Karl "Una razón para usar paréntesis sería si quisiera evaluar una expresión antes de regresar" ¿Puede dar un ejemplo de esto? –

+0

@ChrisMiddleton No, porque la afirmación es tan absurda aquí como lo fue en ese hilo. No hay diferencia funcional alguna entre 'return m * x + c' y' return (m * x + c) 'o' return ((m * x) + c) 'o etc. - y no se ve mejor o más intuitivo tampoco, si me preguntas. –

2

No, no hay diferencia en su código.

2

Asumo boo es un error, y se preguntan si existe una diferencia entre

return expr; 

y

return(expr); 

La respuesta es no.

3

AFAIK, nada es diferente.

En C++, las expresiones pueden tener la forma: expr o (expr). Entonces, este último es una expresión con más tipeo. Para leer más sobre esto, consulte a grammar (busque "expresión").

+0

David, gracias por el enlace.Tengo la gramática en el libro C++ de Stroustrup, pero (por pereza, supongo) no la veo tanto, ahora que la tengo marcada en mi navegador puedo referirme a ella más a menudo. –

3

Los paréntesis en el ejemplo superior son superfluos; ellos son efectivamente ignorados.

Sería lo mismo que algo como ...

int x = (5); 

El paréntesis se omiten aquí también.

+0

Bueno, técnicamente, no están * ignorados *, simplemente no tienen ningún efecto sobre el valor de la expresión. –

+0

@John: * efectivamente * ignorado. :) – James

+3

+1 ... esta es la única respuesta que establece que los paréntesis son en realidad * redundantes * y muestra que su uso es un poco estúpido. –

1

No hay diferencia entre los dos, aunque puede incluir paréntesis si hace que la expresión sea fácil de leer y borrar.

+0

... pero nunca lo hace. ¿Por qué lo haría? ¿Qué es difícil de leer sobre una expresión sin apariencia? Agregar paréntesis solo me parece desordenado. En cuanto a parecer más claro, ¿la gente piensa que 'return' es un operador codicioso y que' return m * x + c' podría devolver 'm' y descartar el resto, o qué? –

1

¡Estás ralentizando el compilador de forma abusiva!

La presencia de paréntesis no solo desacelera la fase de preprocesamiento, sino que también genera un Árbol de sintaxis abstracta más complicado: más memoria, más cómputo.


Desde un punto de vista semántico? Ellos son exactamente idénticos. Si hay paréntesis o no, la instrucción return evaluará completamente la expresión antes de devolverla.

+4

Mi pensamiento exactamente. Al hacer que el compilador haga un trabajo innecesario al analizar el desorden inútil, se está acercando a la muerte por calor del universo sin una buena razón. –

+0

¿Cómo te sientes acerca de los bitcoins? –

1

Son idénticos. Veo la sintaxis de paréntesis con bastante frecuencia, y siempre pregunto a quienes la usan: ¿por qué? Y ninguno puede responder por qué lo usan.

Para resumir sin rodeos, las personas que no comprenden la diferencia entre macros y funciones y confunden la precedencia del operador o el orden de las reglas de evaluación utilizan expresiones de paréntesis. No hay beneficio de estilo de codificación al usar paréntesis.

Así

return value; 

es más correcto que

return (value) 

porque este último sugiere que no sé muy bien lo que está haciendo :)

-4

Ambos son iguales en su caso.

+0

Esta respuesta es incorrecta –

+0

M.M ¿podría explicar su comentario? –

+0

si 'a' es' 5', 'return a ++;' y 'return (a ++);' (que es lo mismo) devolverán '5' –

Cuestiones relacionadas