Skip to content

Punteros, funciones, referencias, ZOMG

25 enero 2010

Las dos y veinte de la mañana y yo aquí dudando de mi valor como informático. Me regalaron por reyes el libro “Beyond the C++ Standard Library: An Introduction to Boost“, para aprender un poco Boost, ya que los desarrolladores de Gosu lo usan y recomiendan usarlo.

Total, que tras haberme leído la parte de los scoped_ptr me metí con la sección de los shared_ptr, y tras leerla me intenté hacer un código para probar por mí mismo cómo funcionaba y sus bondades y tal. Creé una clase Elemento y otra clase Contenedor con un shared_ptr a Elemento. Hasta ahí todo bien, funcionaba y tal, así que para darle más emoción trasladé la creación del Elemento original a una función aparte, a la que le pasaba los punteros a los objetos Contenedor (aún no creados).

Fallo de segmentación.

Wat? Perdoneusté, ¿cómo que fallo de segmentación? Dándole vueltas, al final reduje el error a su mínima expresión en el siguiente testcase:

#include <iostream>
#include <string>

using namespace std;

void create(string * myString){
  myString = new string("This is the text");
  cout << *myString << endl;
}

int main(){
  string * myString = NULL;
  create(myString);
  cout << *myString << endl;
  return 0;
}

Si lo probáis, veréis que en el segundo cout da un petazo. Y yo pensando, si le estoy pasando un puntero a la función, y ésta lo rellena, ¿por qué el puntero original no sale relleno? Al final acabé preguntando en el IRC y me respondieron con la solución: usar una referencia, y ya lo entendí.

En ese código, lo que le pasamos a la función es la dirección de memoria del contenido del puntero, no el puntero en sí mismo. Pero claro, como el puntero no apunta a nada en este caso, pues no alberga una dirección de memoria concreta, y al rellenar dentro de la función, no hay forma de devolverle al puntero original esa información. Para eso usamos una referencia: simplemente cambiando la cabecera de la función a void create(string *& myString) ya le estaremos pasando a la función una referencia a un puntero a cadena, concretamente el puntero myString del main, por lo que ambos myString (el de la función y el del main) no solo apuntarán al mismo espacio de memoria, sino que serán virtualmente el mismo.

Y esto lo escribo para acordarme para otra ocasión, que luego me pasa lo mismo y se me olvida.

2 comentarios leave one →
  1. 25 enero 2010 8:43

    OH MY!

    Entonces lo que hacemos en bison de :

    // lexico.l

    [a-zA-Z] {yylval.nom = new string(yytext); return ID;}

    // parser.y

    …{cout << *$1;}…

    ¿No debería petar igualmente? Lo cierto es que es un poco bizarro este asunto.

  2. 25 enero 2010 11:14

    Las maravillas de C++. Pasan los años y el lenguaje sigue haciendo aguas por los mismos sitios. Viva Stroustrup y su sentido de la ortogonalidad

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: