0

Estoy aprendiendo C++ y haciendo un pequeño juego he tenido que pasar un objeto como parámetro por referencia. He pensado algo como esto:

void function(OBJECT* obj) {
     std::cout << obj->x;
}

Y luego:

OBJECT obj(2);
function(&obj);  //2

El parámetro es un puntero para luego pasar el parámetro por referencia. Eso he pensado. Pero luego vi en internet una cosa parecida, algo como esto:

function(OBJECT &obj) {
    std::cout << obj.x;
}

Y lógicamente ahora se llama a la funcion con 'obj', no con '&obj'. Entonces mi pregunta es: ¿cual es la diferencia?

Por ejemplo entre esto:

class Carretera {
  public:
    int limite_der, limite_izq;
    Road(int _limite_der, int _limite_izq) : limite_der(_limite_der), limite_izq(_limite_izq) {}
};
class Coche {
    int x;
  public:
    Coche(int _x) : x(_x) { };
    void mover(Carretera* c);
};
void Coche::mover(Carrtera* c) {
    while (this->x >= c->limite_der) {
        this->x++;
    }
}
int main() {
    Carretera carr(0, 20);
    Coche coche(carr.limite_der);
    coche.mover(&carr); 
    return 0;
}

y esto:

class Carretera {
    ...
}
class Coche {
    int x;
  public:
    Coche(int _x) : x(_x) { };
    void mover(Carretera &c); //Cambiado
};
void Coche::mover(Carretera &c) { //Cambiado
    while (this->x >= c.limite_der) { //Cambiado r->limite_der por r.limite_der
        this->x++;
    }
}
int main() {
    Carretera carr(0, 20);
    Coche coche(carr.limite_der);
    coche.move(carr); //Cambiado
    return 0;
}

¿Hay alguna diferencia? ¿Qué es lo más correcto? ¿Por qué cambia la forma en la que accedo a un método o propiedad? (road->limit_r cambia a road.limit_r)

Cabe aclarar que creo que entiendo como funcionan los punteros y las referencias, lo que no entiendo es cual es la diferencia exacta entre hacerlo de una forma u otra, y sobre todo, no entiendo por qué cambia la forma de acceder a propiedades o métodos del objeto.

Muchas gracias, y disculpen mi ignorancia.

Emile
  • 13
  • 3
  • *¿Por qué cambia la forma en la que accedo a un método o propiedad?* -> El acceso mediante punto no puede utilizarse con punteros ya que el punto tiene mayor precedencia que el `*`, lo que hace que se ejecute antes la parte del punto que el acceso al objeto referenciado. En cuanto a diferencias, aparte de permitir el acceso correcto a los objetos la flecha (`->`) puede sobrecargarse para añadirle otras funcionalidades. Por lo demás, son lo mismo excepto que la flecha espera una referencia y al usarla lo primero que hace es *dereferenciar* el objeto, es decir, es lo mismo que hacer: `(*obj).x` – Benito-B Dec 30 '21 at 22:31
  • *"¿cual es la diferencia?"*. En uno usas punteros y en otro referencias. Estas son cosas diferentes, no las vayas a confundir. *"no entiendo por qué cambia la forma de acceder a propiedades o métodos del objeto"*, honestamente aqui no hay nada que entender. Esa son de las cosas que son asi porque asi se le ocurrio al creador del lenguaje, y asi decidio que tenia que ser. – Pablochaches Dec 31 '21 at 01:03
  • es una mejora que se le hizo a c++ con respecto a c. En c, int x, *p luego p = &x y pasar p como parametro, que seria la direccion de memoria de x. En c++ int x, pasas &x que seria la direccion de x, mas sencillo – Hernán Garcia Dec 31 '21 at 01:31
  • @Pablochaches En uno paso un puntero y en otro referencia. Lo entiendo. ¿Pero se obtiene el mismo resultado, no? Una función suma1(int* n) { *n+=1; } a la que luego le pases un puntero hará lo mismo que una suma1(int &n) { n += 1; }; De ahí mi duda – Emile Jan 02 '22 at 15:07
  • Cambia la sintaxis, y también cambia lo que puedes hacer dentro de la función con el parámetro recibido. Tal como lo estás usando, ambas sintaxis producen el mismo resultado y por tanto en cierto modo son equivalentes. Pero el utilizar un puntero te permite tener acceso por separado al valor del puntero en sí y al valor apuntado por el puntero. Cuando trabajas con referencias solo tienes "el valor apuntado" por asi decir. Con los punteros puedes hacer aritmética de punteros, con las referencias no. El puntero podrías cambiarlo para que apunte a otro sitio, a la referencia no. – abulafia Jan 02 '22 at 15:45
  • Finalmente, si `p` es un puntero, que apunta a `x`, `&p` te dará en qué dirección de memoria está almacenado el propio puntero (mientras que `p` sería en qué dirección está el dato al que apunta, es decir, `&x`). En el caso de una referencia `r` a un parámetro `x`, la referencia es sólo otro nombre (alias) para la variable `x`, por lo que `&r` te dará la misma dirección que `&x` – abulafia Jan 02 '22 at 15:49

1 Answers1

0

Para entender mejor esa difrencia entre punteros y referencia, es necesario entender un poco las diferencias entre Stack vs Heap(aqui hay informacion mas detallada).

Los punteros son usandos normalmente cuando se hace de memoria dinamica(Heap), usando el operador new:

Object* object = new Object();

en este caso se aloca un objecto en la memoria y el unico modo de usarlo es por medio de ese nuevo puntero 'object'. Es importante recordar que cuando se aloca memoria de manera dinamica es obligatorio limpiar o puede provocar un memory leak. con el operador delete:

delete object;

entonces la diferencia real entre puntero y referencia, es netamente que el puntero es un objecto con funcionalidades que permiten usar la memoria de manera dinamica, mientras que la referencia no es mas que una manera mas segura de usar un objecto en una direccion de memoria en especifico. Como el puntero cumple su funcion de apuntar a la direcion en la memoria, por eso se usa el operador -> para acceder a los attributos o metedos del objecto alocado en esa direcion.

Una principal diferencia entre puntero y referencia cuando es usada como paramtero de una funcion como es su caso, es que el puntero puede tener un valor de NULL, mientras que la refencia no puede tenerlo ya que causaria Undefined Behavior, entonces eso permite algo de dinamismo cuando es obligatorio que exista el objecto en memoria o no.

En cuanto a cual es el metodo correcto si puntero o referencia, eso depentede totalmente de su programa y de lo que desee hacer, si usa objecto alocados de manera dinamica o no, si solo desea manipular el valor de una variable y no hacer una 'copia' de la misma, etc.

Steback
  • 46
  • 3