referencias - punteros en c++ ejercicios resueltos pdf
Puntero vs. referencia (12)
¿Qué sería una mejor práctica al dar a una función la variable original para trabajar con:
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?
Considere la palabra clave fuera de C #. El compilador requiere que la persona que llama a un método aplique la palabra clave out a cualquier argumento out, aunque ya sepa si lo son. Esto está destinado a mejorar la legibilidad. Aunque con los IDEs modernos, me inclino a pensar que este es un trabajo para el resaltado de sintaxis (o semántico).
Debe pasar un puntero si va a modificar el valor de la variable. A pesar de que, técnicamente, pasar una referencia o un puntero son 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.
En última instancia, esto termina siendo subjetivo. La discusión hasta ahora es útil, pero no creo que haya una respuesta correcta o decisiva para esto. Mucho dependerá de las pautas de estilo y sus necesidades en el momento.
Si bien hay algunas capacidades diferentes (ya sea que algo pueda ser NULL o no) con un puntero, la mayor diferencia práctica para un parámetro de salida es puramente sintaxis. La Guía de estilo de C ++ de Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), por ejemplo, solo asigna punteros para los parámetros de salida y solo permite referencias constantes. El razonamiento es de legibilidad: algo con sintaxis de valor no debería tener un significado semántico. 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.
Mi regla de oro es:
Use punteros si desea hacer aritmética de punteros con ellos (por ejemplo, incrementando la dirección del puntero para pasar por una matriz) o si alguna vez tiene que pasar un puntero NULO.
Utilice referencias de lo contrario.
Pase por referencia constante, a menos que haya una razón por la que desee cambiar / conservar los contenidos que está transmitiendo.
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 proporciona a los demás usuarios una buena indicación de lo que la función hace a los valores pasados. Esto incluye hacer una constante de puntero cuando solo desea cambiar lo que se apunta a ...
Punteros:
- Se puede asignar
nullptr
(oNULL
). - En el sitio de la llamada, debe usar & si su tipo no es un puntero en sí mismo, lo que explica que está modificando su objeto.
- Los punteros pueden ser de rebote.
Referencias:
- No puede ser nulo.
- Una vez atado, no se puede cambiar.
- Las personas que llaman no necesitan usar explícitamente &. Esto a veces se considera malo porque debe ir a la implementación de la función para ver si se modifica su parámetro.
Realmente creo que se beneficiará de establecer la siguiente función llamando a las directrices de codificación:
Como en todos los demás lugares, siempre sea
const
correcto.- Nota: Esto significa, entre otras cosas, que solo los valores fuera de valor (ver elemento 3) y los valores pasados por valor (ver elemento 4) pueden carecer del especificador
const
.
- Nota: Esto significa, entre otras cosas, que solo los valores fuera de valor (ver elemento 3) y los valores pasados por valor (ver elemento 4) pueden carecer del especificador
Solo pase un valor por puntero si el valor 0 / NULL es una entrada válida en el contexto actual.
Razón 1: Como persona que llama , usted ve que todo lo que pase debe estar en un estado utilizable.
Razón 2: Como se llama , usted sabe que todo lo que entra está en un estado utilizable. Por lo tanto, no es necesario realizar una comprobación NULA o un manejo de errores para ese valor.
Justificación 3: Las justificaciones 1 y 2 se aplicarán al compilador . Siempre atrapa errores en tiempo de compilación si puedes.
Si un argumento de función es un valor fuera de valor, páselo por referencia.
- Justificación: No queremos romper el artículo 2 ...
Elija "pasar por valor" sobre "pasar por referencia constante" solo si el valor es un POD ( estructura de datos antigua ) o lo suficientemente pequeño (en cuanto a la memoria) o de otra manera lo suficientemente barato (en el tiempo) para copiar.
- Justificación: Evitar copias innecesarias.
- Nota: lo suficientemente pequeño y lo suficientemente barato no son medibles absolutos.
Si tiene un parámetro donde 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::optional . Esto le permite pasar valores opcionales por referencia y también como valor de retorno.
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
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, mi 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 utilizando un puntero.
Use una referencia cuando pueda, use un puntero cuando tenga que hacerlo. De C ++ Preguntas frecuentes: "¿Cuándo debo usar referencias y cuándo debo usar punteros?"
Punteros vs. Referencias
Las referencias son menos poderosas que los punteros:
1) Una vez que se crea una referencia, no se puede hacer posteriormente para hacer referencia a otro objeto; no se puede volver a colocar Esto se hace a menudo con punteros.
2) Las referencias no pueden ser NULL. Los punteros a menudo se hacen NULOS para indicar que no están apuntando a ninguna cosa válida.
3) Una referencia debe ser inicializada cuando se declara. No hay tal restricción con punteros
Debido a las limitaciones anteriores, las referencias en C ++ no se pueden usar para implementar estructuras de datos como Lista enlazada , Árbol, etc. En Java, las referencias no tienen las restricciones anteriores y se pueden usar para implementar todas las estructuras de datos. Las referencias son más poderosas en Java, es la razón principal por la que Java no necesita punteros.
Las referencias son más seguras y fáciles de usar:
1) Más seguro: ya que las referencias deben inicializarse, es poco probable que existan referencias salvajes como punteros de comodín. Todavía es posible tener referencias que no se refieren a una ubicación válida
2) Más fácil de usar: las referencias no necesitan un operador de referencia para acceder al valor. Se pueden utilizar como variables normales. El operador ''&'' solo es necesario en el momento de la declaración. Además, se puede acceder a los miembros de una referencia de objeto con el operador de punto (''.''), A diferencia de los punteros donde se necesita el operador de flecha (->) para acceder a los miembros.
Junto con las razones anteriores, hay algunos lugares como el argumento del constructor de copia donde no se puede usar el puntero. Referencia debe ser utilizada pasar el argumento en el constructor de copia. Se deben usar referencias similares para sobrecargar algunos operadores como ++ .
Punteros
- Un puntero es una variable que contiene una dirección de memoria.
- Una declaración de puntero consta de un tipo base, un * y el nombre de la variable.
- Un puntero puede apuntar a cualquier número de variables en el tiempo de vida.
Un puntero que no apunta actualmente a una ubicación de memoria válida recibe el valor nulo (que es cero)
BaseType* ptrBaseType; BaseType objBaseType; ptrBaseType = &objBaseType;
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.
int nVar = 7; int* ptrVar = &nVar; int nVar2 = *ptrVar;
Referencia
Una referencia (&) es como un alias a una variable existente.
Una referencia (&) es como un puntero constante que se elimina automáticamente.
Normalmente se usa para listas de argumentos de función y valores de retorno de función.
Una referencia debe ser inicializada 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 const.
int i = 3; //integer declaration int * pi = &i; //pi points to the integer i int& ri = i; //ri is refers to integer i – creation of reference and initialization