2009-09-09 11 views
7

referencias en C++ son una construcción conveneint que nos permiten simplificar el siguiente código C:shared_ptr y referencias en C++

f(object *p){ 
    //do something 
} 

int main(){ 
    object* p = (object*) calloc(sizeof(object)); 
    f(p); 
} 

a

f(object& o){ 
    //do something 
} 

int main(){ 
    object o = object(); 
    f(o); 
} 

punteros compartidos son otra comodidad en C++ que simplifican la memoria administración. Sin embargo, no estoy seguro de cómo pasar un shared_ptr a una función como f(object& o) que acepta argumentos por referencia?

f(object& o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(*p); 
} 

¿El puntero compartido se incrementará cuando se pase su objeto por referencia a una función?

+2

En lugar de 'object * p = (object *) calloc (sizeof (object));' debes usar 'object * p = new object();' para que se llame al constructor! (O puede 'calloc' luego placement-'new'.) – strager

+1

Debe esperar unas pocas horas para que la gente tenga tiempo de encontrar y responder a su pregunta, o podrá usar el comando answer-shuffle, y la gente no tendrá una oportunidad de mejorar sus respuestas a través de comentarios-comentarios. Después de pensar que el polvo se ha asentado, seleccione la respuesta más útil. – GManNickG

+0

Lo tendremos en cuenta en el futuro. ¡Gracias! – dzhelil

Respuesta

10

Tome un shared_ptr por valor, y el recuento de referencia se incrementará. Esto es más fácil cuando se typedef:

typedef boost:shared_ptr<object> object_ptr; 

void foo(object_ptr obj) 
{ 
    obj->/* stuff*/; 
    obj.reset(); //only resets this local copy, that means: 
       // reduce reference count (back to 1), and 
       // set obj to point at null. 
} 

int main(void) 
{ 
    object_ptr obj(new object()); 
    foo(obj); 
} 

Tenga en mente las referencias son alias. Cuando pasa por referencia, no está pasando punteros, copias, etc., aliasing otro objeto. (En realidad se implementan como punteros):

typedef boost:shared_ptr<object> object_ptr; 

void foo(object_ptr& obj) 
{ 
    obj.reset(); // the references was never increased, since a copy has not 
       // been made, this *is* obj in main. so the reference 
       // goes to 0, and obj is deleted 
} 

int main(void) 
{ 
    object_ptr obj(new object); 
    foo(obj); // after this, obj has been reset! 
} 

Recuerde siempre ser const correcta, para evitar errores:

typedef boost:shared_ptr<object> object_ptr; 

void foo(const object_ptr& obj) 
{ 
    obj.reset(); // cannot do! 
} 

int main(void) 
{ 
    object_ptr obj(new object); 
    foo(obj); 
} 

Creo que se debe preferir a pasar punteros inteligentes como referencias cuando sea posible, a evitar incrementos y decrementos extraños (y copias y otras cosas).

+3

... y evite pasar los punteros inteligentes como argumentos en absoluto si la función no necesita un puntero inteligente (es decir, no hace una copia para su uso posterior). –

2

¿El puntero compartido se incrementará cuando se pase su objeto por referencia a una función?

No, como está accediendo al puntero sin formato y luego pasándolo. ¿Quieres hacer algo similar a esto:

f(shared_ptr<object> o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(p); 
} 
-1

Lo primero es lo primero, desde el punto de vista de la funcionalidad, las referencias en C++ son exactamente las mismas que las de los punteros. Solo razonaron que se agregaron al lenguaje para hacer que la sintaxis de la sobrecarga del operador fuera más natural. (Por ejemplo, para permitir que uno escriba a + b en lugar de & a + & b)

Sus muestras de códigos C y C++ no son absolutamente equivalentes. La versión C de su código C++ sería:

f(object *p){ 
    //do something 
} 

int main(){ 
    object o; 
    object_constructor(&o); 
    f(&o); 
    object_destructor(&o); 
} 

De hecho, este es el tipo de código que el compilador de C++ conceptualmente generar.

Con respecto a su segunda pregunta: Sí, esa es la forma correcta de llamar a la función f. El contador del puntero compartido no se incrementará. Se pasará el puntero real al objeto, como si no estuviera usando un shared_ptr. Sin embargo, es seguro, siempre y cuando f no esté haciendo nada funky. Solo recuerde que exactamente lo mismo está sucediendo como si el parámetro f tomara un puntero en lugar de una referencia. La única diferencia es que el compilador automáticamente pasa la dirección de la variable sin tener que usar explícitamente el operador &.

Personalmente, no me gusta pasar las variables por referencia (sin embargo, pasar por referencia de referencia está bien). Prefiero usar un puntero en su lugar, ya que lo hace más claro en el sitio de llamadas que la función a la que llamamos puede potencialmente modificar su argumento (ya que el símbolo & está visible en el sitio de llamadas).

Paz

+2

Lo sentimos, pero "las referencias en C++ son exactamente lo mismo que los punteros" es incorrecto. Además, tal vez solo sea estilo, pero creo que la mayoría de los programadores de C++ estarán de acuerdo en pasar punteros en lugar de referencias. Ahora debe verificar nulo todo el tiempo. Las referencias son más naturales. – GManNickG

1
f(object& o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(*p); 
} 

¿El puntero compartida se incrementará cuando su objeto se pasa por referencia a una función?

En el código anterior - no. p tendrá su contador de referencia igual a 1 en todo momento. Puede verificar esto en un depurador. El contador de referencia de shared_ptr cuenta el número de instancias de shared_ptr que apuntan al mismo objeto, no rastrea las referencias creadas llamando al operador *(). Y no tiene que - desde p está garantizada para vivir hasta el final de la amplitud y la llamada a la función es en este mismo ámbito (o más profundo) p estará allí durante toda la llamada a f () Entonces todo está bien.

... a menos que en f se toma la dirección de o y guardarla en algún sitio que va a durar después f devoluciones. Esto debe evitarlo por todos los medios: pase el shared_ptr si necesita hacer eso.