Domanda

I riferimenti in C ++ sono un costrutto conveneint che ci consente di semplificare il seguente codice 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);
}

I puntatori condivisi sono un'altra comodità in C ++ che semplifica la gestione della memoria. Tuttavia, non sono sicuro di come passare un shared_ptr a una funzione come f (object & amp; o) che accetta argomenti per riferimento?

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

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

Il puntatore condiviso verrà incrementato quando il suo oggetto viene passato in riferimento a una funzione?

È stato utile?

Soluzione

Prendi un shared_ptr per valore e il conteggio dei riferimenti aumenterà. Questo è più semplice quando digiti :

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);
}

Ricorda che i riferimenti sono alias. Quando passi per riferimento, non stai passando puntatori, copie, ecc ..., stai aliasando un altro oggetto. (In realtà sono implementati come puntatori):

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!
}

Ricorda sempre di essere const corretto, per evitare errori:

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);
}

Penso che dovresti preferire passare puntatori intelligenti come riferimenti quando possibile, per evitare incrementi e decrementi estranei (e copie e quant'altro).

Altri suggerimenti

  

Il puntatore condiviso verrà incrementato quando il suo oggetto viene passato in riferimento a una funzione?

No, mentre accedi al puntatore non elaborato e poi lo passi. Vuoi fare qualcosa di simile a questo:

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

int main(){
  shared_ptr<object> p (new object());
  f(p);
}
f(object& o){
  //do something
}

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

Il puntatore condiviso verrà incrementato   quando il suo oggetto viene passato per riferimento   a una funzione?

Nel codice sopra - no. p avrà il suo contatore di riferimento uguale a 1 in ogni momento. Puoi verificarlo in un debugger. Il contatore dei riferimenti di shared_ptr conta il numero di istanze shared_ptr che puntano allo stesso oggetto, non tiene traccia dei riferimenti creati chiamando l'operatore * (). E non è necessario, poiché p è garantito fino al termine dell'ambito e la chiamata di funzione è nello stesso ambito (o più profonda) p sarà lì durante l'intera chiamata a f (). Quindi va tutto bene.

... a meno che in f prendi l'indirizzo di o e conservi un posto che durerà dopo il ritorno di f . Questo dovresti evitare in ogni caso: passa il file shared_ptr se devi farlo.

Per prima cosa, dal punto di vista della funzionalità, i riferimenti in C ++ sono esattamente gli stessi dei puntatori. Il solo motivo per cui sono stati aggiunti al linguaggio è quello di rendere più naturale la sintassi del sovraccarico dell'operatore. (Ad esempio per consentire a uno di scrivere a + b invece di & amp; a + & amp; b)

I tuoi esempi di codice C e C ++ non sono assolutamente equivalenti. La versione C del tuo codice C ++ sarebbe:

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

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

In realtà, questo è il tipo di codice che il tuo compilatore C ++ genererà concettualmente.

Per quanto riguarda la tua seconda domanda: Sì, questo è il modo corretto di chiamare la funzione f. Il contatore del puntatore condiviso non verrà incrementato. Il puntatore effettivo all'oggetto verrà passato, come se non si stesse usando shared_ptr. Tuttavia, è sicuro, purché f non stia facendo nulla di strano. Ricorda solo che sta succedendo esattamente le stesse cose come se il parametro di f prendesse un puntatore anziché un riferimento. L'unica differenza è che il compilatore passa automagicamente l'indirizzo della variabile senza che tu debba usare esplicitamente & amp; operatore.

Personalmente non mi piace mai passare variabili per riferimento (passare per const const è ok però). Preferisco usare un puntatore invece perché rende più chiaro sul sito della chiamata che la funzione che stiamo chiamando potrebbe potenzialmente modificare il suo argomento (poiché il simbolo & amp; è visibile sul sito della chiamata).

Pace

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top