Quando passare per riferimento e quando passare da un puntatore in C ++?

Situazioni comuni:

  1. Passando std :: string a una funzione foo (std :: string *) o foo (std :: string &);
  2. Passando tr1 :: shared_ptr a una funzione foo (tr1 :: shared_ptr * ptr) o foo (tr1 :: shared_ptr & ptr);

In generale, ciò che è una buona pratica. Mi confondo sempre. All’inizio, passare tutto come riferimenti sembra coerente, tuttavia non è ansible passare in Letterali come riferimenti o NULL come riferimenti.

Allo stesso modo, avere tutto come puntatori sembra buono, ma avendo allora devo preoccuparmi che i puntatori potrebbero puntare a NULL e controllare quelle condizioni all’inizio di quella funzione.

Pensi che il seguente frammento sia buono?

#include  #include  #include  #include  #include  #include  using namespace std; using namespace std::tr1; int main(){ map<string, shared_ptr<vector > > adjacencyMap; vector* myFriends = new vector(); myFriends->push_back(string("a")); myFriends->push_back(string("v")); myFriends->push_back(string("g")); adjacencyMap["s"] = shared_ptr<vector >(myFriends); return 0; } 

Grazie Ajay

I riferimenti sono più facili da ottenere.

Il tuo problema con i letterali è che non stai usando riferimenti const? Non è ansible associare un riferimento temporaneo (prodotto da un valore letterale) a un riferimento non const, perché non ha senso modificarne uno. È ansible associare uno a un riferimento const.

In particolare, quando si passa un argomento a una funzione e la funzione non lo cambierà e non è un tipo predefinito, passa per riferimento const. Funziona in modo analogo al passaggio per valore, tranne per il fatto che non richiede una chiamata al costruttore di copia.

I puntatori sono utili in quanto hanno un valore invalido garantito che puoi testare. A volte questo è irrilevante, ea volte è molto importante. Ovviamente, non è generalmente ansible passare letteralmente un puntatore, a meno che (nel caso di una stringa letterale) lo sia già.

Alcuni standard di codifica dicono che nulla dovrebbe mai essere passato da riferimento non const, poiché non fornisce alcuna indicazione sul punto di chiamata che l’argomento possa essere modificato dalla funzione. In tal caso, ti verrà richiesto di passare da un puntatore. Non sono favorevole a questo, in particolare perché gli strumenti di programmazione rendono più facile e più semplice ottenere la firma della funzione, in modo da poter vedere se una funzione potrebbe cambiare un argomento. Tuttavia, quando si lavora in un gruppo o per un’impresa, la coerenza dello stile è più importante di ogni singolo elemento di stile.

Una buona regola empirica: “Usa i riferimenti quando puoi e i puntatori quando devi”.

Non capisco davvero perché tu abbia avuto tutto questo problema:

 std::map < std::string, std::vector > adjacencyMap; std::vector& sFriends = adjacencyMap["s"]; sFriends.push_back("a"); sFriends.push_back("v"); sFriends.push_back("g"); 

Perché ti intrometti con shared_ptr qui? La situazione certamente non lo richiede!

Nel mio precedente lavoro, avevamo la regola che i semplici riferimenti non erano praticamente mai usati. Invece abbiamo accettato di:

  • passa per valore (a buon mercato per copiare oggetti, tutti i primitivi, piccoli tipi di valore, std :: string , stringhe molto piccole o refcounted)
  • passare per riferimento const (per accesso in sola lettura a oggetti di grandi dimensioni)
  • passare per puntatore se è necessario l’accesso in lettura-scrittura

Se tutti seguono queste regole, si può presumere che i parametri passati alle funzioni non vengano modificati a meno che il loro indirizzo non sia stato preso. Ha funzionato per noi.

Probabilmente non è una risposta alla domanda. Bacia e basta.

 int main() { multimap adjacencyMap; adjacencyMap.insert(std::make_pair("s", "a")); adjacencyMap.insert(std::make_pair("s", "v")); adjacencyMap.insert(std::make_pair("s", "g")); return 0; } 

È ansible consultare http://www.cplusplus.com/forum/beginner/3958/ per alcuni approfondimenti. Utile anche: http://www.velocityreviews.com/forums/t284603-pointers-vs-references-a-question-on-style.html

Immagino non ci sia una risposta “giusta”. È necessario valutare i pro e i contro di ciascun approccio tenendo conto del contesto specifico del progetto.

Personalmente preferisco i riferimenti, ma consiglio comunque di leggere quei post e di ispirarmi a questo.

Come regola generale, cerca sempre di passare i parametri per riferimento a const. Passaggi puntatori possono portare a problemi di proprietà, nonché un sacco di altre possibilità di errori sottili.

Qual è lo scopo di NULL? Per indicare un puntatore / object non valido. Se hai intenzione di passare oggetti non validi a una funzione, tutto ciò che devi fare è avere un metodo per verificare la validità di un object. Come in:

 void myfunc(const obj& myobj) { if(myobj.valid()) // DO SOMETHING } 

Tipi primitivi che di solito vuoi passare per valore, dato che c’è un piccolo sovraccarico. E questo è il momento in cui useresti i letterali per lo più la maggior parte del tempo. Per le stringhe, dovresti provare a usare std::string e stare lontano dalle stringhe in stile C const char* il più ansible. Ovviamente se devi usare stringhe di tipo C, non hai altra scelta che usare i puntatori, ma tutti i riferimenti dovrebbero essere la strada da percorrere.

Oh e per essere veramente sicuro alle eccezioni, cerca di evitare questo:

 vector* myFriends = new vector(); ... adjacencyMap["s"] = shared_ptr >(myFriends); 

Invece:

 shared_ptr > myFriends(new vector()); 

Guarda in RAII e sicurezza delle eccezioni per il motivo per cui questo è il metodo preferito.

preferirei

  map > > adjacencyMap; shared_ptr > myFriends(new vector()); myFriends->push_back(string("a")); myFriends->push_back(string("v")); myFriends->push_back(string("g")); adjacencyMap["s"] = myFriends; return 0; 

in quanto ciò garantisce che la gestione locale delle variabili sia sicura per le eccezioni.

Non vedo davvero come questo affronta la tua q che riguardava il merito di ref vs ptr, però. In entrambi gli esempi citati mi aspetterei di utilizzare la seconda forma (ref).