En Otras características de C ++, Argumentos de referencia de la Guía de estilo de Google C ++ , leí que no se deben usar referencias no constantes.
Todos los parámetros pasados por referencia deben etiquetarse const.
Está claro que mirar las llamadas a funciones que usan referencias como argumentos es absolutamente confuso para los programadores de C, pero C y C ++ son lenguajes diferentes ahora. Si se requiere un parámetro de salida , el uso de un puntero para un parámetro de salida requerido puede hacer que se omita todo el cuerpo de la función, lo que hace que la implementación de una función sea más complicada (aumenta formalmente la complejidad y profundidad ciclomática de una función).
Me gustaría hacer que el código C ++ sea lo más fácil de entender / mantener posible, por lo que generalmente estoy interesado en leer las guías de estilo de codificación. Pero para adaptar las mejores prácticas en un equipo, creo que comprender el fundamento de los elementos de la guía de estilo es un factor importante.
¿Las referencias no constantes son realmente tan malas? ¿Prohibirlos solo es específico de Google o es una regla comúnmente aceptada? ¿Qué justifica el esfuerzo adicional para implementar parámetros de salida como punteros?
Respuestas:
La razón detrás de la guía de estilo de Google es simplemente dejar en claro desde el sitio de llamadas de una función si un parámetro es un parámetro de entrada o un parámetro de salida. (Ver aquí para una discusión más detallada). Otros lenguajes establecen parámetros explícitos por diseño; C #, por ejemplo, tiene una
out
palabra clave que debe usarse en el sitio de la llamada . Como C ++ no lo hace explícito, Google eligió usar const ref. versus puntero para que quede claro.¿Es esto solo una regla de Google? No, pero dudo que esté muy extendido. No creo haberlo visto fuera de la guía de estilo y los grupos de Google que se adhieren explícitamente a partes de la guía de estilo de Google. (Por ejemplo, me gustó la idea cuando leí por primera vez la guía de estilo de Google hace años y la he usado para algunos de mis propios códigos).
En particular, las recientemente anunciadas Pautas principales de C ++ prefieren los valores de retorno a los parámetros de salida para (casi) todo y utilizan referencias sin constantes para el resto. El uso de punteros de Google en comparación con las referencias podría aclarar los parámetros de salida, pero los valores de retorno son aún más claros. Ahora que C ++ 11 tiene movimientos estandarizados (referencias de valor,
&&
para hacer que los retornos de muchos tipos sean baratos) y tuplas (lo que permite una manera fácil de devolver múltiples valores), muchos de los casos de uso para parámetros ya no se aplican.Las Pautas principales de C ++ tienen algunos grandes nombres (Bjarne Stroustrup, Herb Sutter) detrás de ellas, son compatibles con Microsoft y adoptan las últimas características de C ++ (a diferencia de la guía de estilo de Google), por lo que espero que sus recomendaciones sean más populares que las de Google.
fuente
Hay 2 opciones para lidiar con un puntero no válido pasado, primero verificar y regresar temprano o dejar que sea un comportamiento indefinido (si le importa más la velocidad que la robustez).
La comprobación es tan simple como:
Este tipo de verificación generalmente se acepta como una verificación de parámetros. Si ve el código, está bastante claro que espera que se pase un puntero no nulo y que regrese temprano si no es así. Esto le permite no preocuparse tanto por punteros inválidos.
fuente
assert(buffer);
Sabiendo que la afirmación está activa solo para la versión de depuración, a veces deseo tener unart_assert(buffer);
que arroje una excepción. La sangría de lareturn
apariencia es un poco peligrosa ... Por cierto: su fragmento de código es una buena ilustración de mi pregunta sobre los punteros para la salida.Todo se reduce a tu observación
If an output parameter is required
.El único lugar donde se requiere una firma de función para tener un parámetro de salida es cuando es especificada por una API externa, y en tal caso simplemente envuelve la API externa en algo que asegura que siempre haya un puntero válido.
Internamente, evita los parámetros de salida extendiendo el tipo de retorno para que sea un compuesto de todas las "salidas"
fuente
The only place where...
es realmente aplicable a todos los casos. Aspecto que sugiere: evite los parámetros de salida en las funciones de sus propios programas. Es cierto para los nuevos programas.