Lo que sería una mejor práctica al dar a una función la variable original con la que trabajar:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
o:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: ¿Hay alguna razón para elegir uno sobre otro?
Respuestas:
Mi regla de oro es:
Utilice punteros si desea hacer aritmética de punteros con ellos (por ejemplo, incrementar la dirección del puntero para recorrer una matriz) o si alguna vez tiene que pasar un puntero NULL.
Use referencias de otra manera.
fuente
Base* b = new Derived()
)? Este parece un caso que no se puede manejar sin punteros.Realmente creo que se beneficiará al establecer las siguientes pautas de codificación de llamadas a funciones:
Como en todos los otros lugares, siempre sea
const
correcto.const
especificador.Solo pase un valor por puntero si el valor 0 / NULL es una entrada válida en el contexto actual.
Justificación 1: como llamante , verá que todo lo que pase debe estar en un estado utilizable.
Justificación 2: Como se llama , usted sabe que todo lo que entra está en un estado utilizable. Por lo tanto, no es necesario realizar ninguna comprobación de NULL o manejo de errores para ese valor.
Justificación 3: Las justificaciones 1 y 2 se aplicarán al compilador . Siempre puede detectar errores en tiempo de compilación si puede.
Si un argumento de función es un valor externo, páselo por referencia.
Elija "pasar por valor" sobre "pasar por referencia constante" solo si el valor es un POD ( Estructura de datos antigua simple ) o lo suficientemente pequeño (en cuanto a memoria) o en otras formas lo suficientemente barato (en cuanto a tiempo) para copiar.
fuente
std::vector<>
.Esto finalmente termina siendo subjetivo. La discusión hasta el momento es útil, pero no creo que haya una respuesta correcta o decisiva a esto. Mucho dependerá de las pautas de estilo y sus necesidades en ese momento.
Si bien hay algunas capacidades diferentes (si algo puede ser NULO o no) con un puntero, la mayor diferencia práctica para un parámetro de salida es puramente sintaxis. La Guía de estilo C ++ de Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), por ejemplo, exige solo punteros para los parámetros de salida y solo permite referencias que sean constantes. El razonamiento es de legibilidad: algo con sintaxis de valor no debe tener un significado semántico de puntero. No estoy sugiriendo que esto sea necesariamente correcto o incorrecto, pero creo que el punto aquí es que es una cuestión de estilo, no de corrección.
fuente
Debe pasar un puntero si va a modificar el valor de la variable. Aunque técnicamente pasar una referencia o un puntero es lo mismo, pasar un puntero en su caso de uso es más legible ya que "anuncia" el hecho de que la función cambiará el valor.
fuente
const
o noconst
, pero puedes ver si el parámetro pasó ala&x
vs.x
y usar esa convección para codificar si el parámetro puede modificarse. (Dicho esto, hay momentos en los que querrás pasar unconst
puntero, por lo que la convección es solo una pista. Argumentable sospechar que algo podría modificarse cuando no sea así es menos peligroso que pensar que no será cuando será ....)Si tiene un parámetro en el que puede necesitar indicar la ausencia de un valor, es una práctica común hacer que el parámetro sea un valor de puntero y pasar NULL.
Una mejor solución en la mayoría de los casos (desde una perspectiva de seguridad) es usar boost :: opcional . Esto le permite pasar valores opcionales por referencia y también como valor de retorno.
fuente
Use una referencia cuando pueda, use un puntero cuando sea necesario. Desde C ++ FAQ: "¿Cuándo debo utilizar referencias, y cuando debo usar punteros?"
fuente
Punteros
Un puntero que actualmente no apunta a una ubicación de memoria válida recibe el valor nulo (que es cero)
El & es un operador unario que devuelve la dirección de memoria de su operando.
El operador de desreferenciación (*) se utiliza para acceder al valor almacenado en la variable a la que apunta el puntero.
Referencia
Una referencia (&) es como un alias de una variable existente.
Una referencia (&) es como un puntero constante que se desreferencia automáticamente.
Generalmente se usa para listas de argumentos de funciones y valores de retorno de funciones.
Se debe inicializar una referencia cuando se crea.
Una vez que se inicializa una referencia a un objeto, no se puede cambiar para referirse a otro objeto.
No puede tener referencias NULL.
Una referencia constante puede referirse a una constante int. Se realiza con una variable temporal con valor de la constante
fuente
Una referencia es un puntero implícito. Básicamente, puede cambiar el valor al que apunta la referencia, pero no puede cambiar la referencia para que apunte a otra cosa. Entonces, mis 2 centavos es que si solo desea cambiar el valor de un parámetro, páselo como referencia, pero si necesita cambiar el parámetro para que apunte a un objeto diferente, páselo con un puntero.
fuente
Considere la palabra clave de C #. El compilador requiere que el llamador de un método aplique la palabra clave out a cualquier argumento out, aunque ya sabe si lo está. Esto está destinado a mejorar la legibilidad. Aunque con los IDE modernos, me inclino a pensar que este es un trabajo para resaltar la sintaxis (o semántica).
fuente
Pase por referencia constante a menos que haya una razón por la que desea cambiar / conservar el contenido que está pasando.
Este será el método más eficiente en la mayoría de los casos.
Asegúrese de usar const en cada parámetro que no desee cambiar, ya que esto no solo lo protege de hacer algo estúpido en la función, sino que le da una buena indicación a otros usuarios de lo que la función hace a los valores pasados. Esto incluye hacer un puntero constante cuando solo quieres cambiar lo que se señala ...
fuente
Punteros:
nullptr
(oNULL
).&
si su tipo no es un puntero en sí mismo, lo que explícitamente está modificando su objeto.Referencias
&
. Esto se considera a veces malo porque debe ir a la implementación de la función para ver si se modifica su parámetro.fuente
Una referencia es similar a un puntero, excepto que no necesita usar un prefijo ∗ para acceder al valor al que hace referencia la referencia. Además, no se puede hacer una referencia para referirse a un objeto diferente después de su inicialización.
Las referencias son particularmente útiles para especificar argumentos de función.
Para obtener más información, consulte "Un recorrido por C ++" de "Bjarne Stroustrup" (2014) Páginas 11-12
fuente