2009-09-09 19 views
7

Riferimenti in C++ sono un costrutto conveneint che ci permettono di semplificare il seguente codice C:shared_ptr e riferimenti in 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); 
} 

puntatori in comune sono un altro vantaggio in C++ che semplifica la memoria gestione. Tuttavia, non sono sicuro di come passare un shared_ptr a una funzione come f(object& 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 per riferimento a una funzione?

+2

Invece di 'oggetto * p = (oggetto *) calloc (sizeof (oggetto));' si dovrebbe usare 'oggetto * p = nuovo oggetto();' così viene chiamato il costruttore! (Oppure puoi usare 'calloc' e posizionare -nuovo'.) – strager

+1

Dovresti aspettare qualche ora per dare alle persone il tempo di trovare e rispondere alla tua domanda, o dovrai dare una risposta shuffle, e le persone non avranno una possibilità di migliorare le loro risposte attraverso commenti-feedback. Dopo aver pensato che la polvere si sia stabilizzata, seleziona la risposta più utile. – GManNickG

+0

Lo avrà in mente in futuro. Grazie! – dzhelil

risposta

10

Take a shared_ptr per valore, e il conteggio di riferimento aumenterà. Questo è più facile quando si è 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); 
} 

Tenete a mente i riferimenti sono alias. Quando passi per riferimento, non stai passando puntatori, copie, ecc ..., stai facendo aliasing di un altro oggetto. (In realtà essi 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! 
} 

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

Credo che si dovrebbe preferire di passare puntatori intelligenti come riferimenti quando possibile, di evitare incrementi e decrementi esterni (e copie e quant'altro).

+3

... ed evita di passare i puntatori intelligenti come argomenti se la funzione in realtà non ha bisogno di un puntatore intelligente (cioè non crea una copia per un uso futuro). –

2

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

No, come si accede al puntatore raw e quindi lo si passa. Si vuole fare qualcosa di simile a questo:

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

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

Per prima cosa, da un punto di vista della funzionalità, i riferimenti in C++ sono esattamente gli stessi dei puntatori. La ragione per cui sono stati aggiunti al linguaggio è stata quella di rendere più naturale la sintassi del sovraccarico dell'operatore. (Ad esempio per consentire a uno di scrivere un + b anziché & a + & b)

I tuoi campioni di codice C e C++ non sono assolutamente equivalenti. La versione C del 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 compilatore C++ saranno concettualmente generare.

Riguardo alla seconda domanda: Sì, questo è il modo corretto per chiamare la funzione f. Il contatore puntatore condiviso non verrà incrementato. Il puntatore effettivo all'oggetto verrà passato, come se tu non stessi usando un shared_ptr. È sicuro, tuttavia, f fesso non sta facendo nulla di strano. Basta ricordare che la stessa cosa sta accadendo esattamente come se il parametro di f avesse un puntatore invece di un riferimento. L'unica differenza è che il compilatore passa automagicamente l'indirizzo della variabile senza dover utilizzare esplicitamente l'operatore &.

Personalmente non mi piace mai passare le variabili per riferimento (passando da riferimento const è ok però). Preferisco invece utilizzare un puntatore poiché rende più chiaro al sito di chiamata che la funzione che stiamo chiamando potrebbe potenzialmente modificare il suo argomento (dal momento che il simbolo & è visibile nel sito di chiamata).

Pace

+2

Ci scusiamo, ma "i riferimenti in C++ sono esattamente uguali ai puntatori" è sbagliato. Inoltre, forse è solo uno stile, ma penso che la maggior parte dei programmatori C++ acconsentirà a far passare i puntatori anziché i riferimenti. Ora devi controllare sempre nulla. I riferimenti sono più naturali. – GManNickG

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

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

Sarà il puntatore condivisa essere 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 di riferimento shared_ptr conta il numero di istanze shared_ptr che puntano allo stesso oggetto, non traccia i riferimenti creati dall'utente chiamando l'operatore *(). E non è necessario - dal momento che p è garantito fino alla fine dell'ambito e la chiamata di funzione è nello stesso ambito (o più profondo) p ci sarà durante l'intera chiamata a f (). Quindi tutto è OK.

... a meno che in f si prende l'indirizzo del o e memorizzare da qualche parte che durerà dopo f rendimenti. Questo dovresti evitare con tutti i mezzi: passa il shared_ptr se hai bisogno di farlo.

Problemi correlati