2011-11-09 16 views
5

Data una classe "A" esiste ed è corretta. Quali sarebbero alcuni dei risultati negativi dell'utilizzo di un riferimento a "A" anziché a un puntatore in una classe "B". Cioè:Quali sono alcuni degli svantaggi dell'utilizzo di un riferimento anziché di un puntatore?

// In Declaration File 
class A; 

class B 
{ 
public: 
    B(); 
    ~B(); 
private: 
    A& a; 
}; 

// In Definition File 
B::B(): a(* new A()) 
{} 

B::~B() 
{ 
    delete &a; 
} 

codice extra Omesso per ulteriori correttezza della "B", come ad esempio la copia costruttore e operatore di assegnamento, voleva solo dimostrare il concetto della questione.

+1

Interessante. Non ho mai visto un codice del genere prima d'ora. Può essere, questo è solo un modo per evitare il dereferenziamento e l'uso di '->' e comunque rendere 'a' assegnato dinamicamente, per qualche motivo:? +1 per la domanda. –

+0

Qual è il punto di questo, invece di solo "A a;'? Non sarebbe meglio di entrambi i riferimenti o puntatori? – tenfour

+1

@tenfour in molti casi, ma è un esempio semplificato - supponiamo che il valore di "a" sia creato da una fabbrica. – justin

risposta

4

Le limitazioni immediate sono che:

  • Non è possibile modificare il valore di un riferimento. È possibile modificare lo A a cui fa riferimento, ma non è possibile riallocare o riassegnare a durante la vita di B.
  • a non deve mai essere 0.

Così:

  • L'oggetto non è assegnabile.
  • B non deve essere copiabile, a meno che non si insegni a A e ai suoi sottotipi di clonare correttamente.
  • B non sarà un buon candidato come elemento di tipi di raccolte se memorizzato come valore. Un vettore di B sarebbe probabilmente implementato più facilmente come std::vector<B*>, che potrebbe introdurre ulteriori complicazioni (o semplificazioni, a seconda del progetto).

Queste possono essere le cose buone, a seconda delle esigenze.

Avvertenze:

  • affettamento è un altro problema di essere a conoscenza di se a è assegnabile e l'assegnazione è raggiungibile in B.
+1

+1 per "queste possono essere cose buone" ... che è quello che penso che siano (supponendo che siano applicabili). Usando un riferimento invece di un puntatore dove possibile documenta il fatto che non è nullo e non cambierà ... informazioni molto utili quando si cerca di dare un senso al codice di qualcun altro. – timday

+0

Modificato per riflettere che il codice mancante era il costruttore della copia e l'operatore di assegnazione. – JadziaMD

+1

Il primo "inconveniente" è _una cosa molto, molto buona_, e il secondo la estende appena. Il fatto che 'B' non sia più assegnabile è anche buono, perché è meglio che' B' sia assegnabile in modo spezzato. –

1

Ovviamente, aggiungendo un membro di riferimento alla classe B significa che il compilatore non può più generare i costruttori impliciti di default e copia e gli operatori di assegnazione; e né un operatore di assegnamento scritto manualmente può rasterizzare a.

Non penso che ci siano risultati negativi, oltre al fatto che delete &a può sembrare strano. Il fatto che l'oggetto sia stato creato da new è in qualche modo perso collegando il risultato a un riferimento e può avere importanza solo dal fatto che il suo tempo di vita deve essere controllato da B non è chiaro.

1

Se si utilizza un riferimento:

  • È necessario fornire il valore in fase di costruzione
  • Non si può cambiare a cosa si riferisce
  • Non può essere nullo
  • Sarà evitare che la classe da assegnabile

Si potrebbe prendere in considerazione l'utilizzo di una smart p ointer di qualche tipo (std :: unique_ptr, std :: shared_ptr, ecc.). Questo ha il vantaggio di eliminare automaticamente l'oggetto per te.

2

Non è possibile modificare l'oggetto indicato da a dopo il fatto, ad es. su incarico. Inoltre, rende il tuo tipo non POD (il tipo dato sarebbe comunque non POD a causa comunque del membro di dati privato, ma in alcuni casi potrebbe essere importante).

Ma lo svantaggio principale è probabilmente potrebbe confondere i lettori del tuo codice.

0

Un riferimento a un oggetto assegnato in modo dinamico viola il principio della sorpresa minima; cioè, normalmente nessuno si aspetta che il codice sia scritto come tu hai. In generale ciò renderà i costi di manutenzione più elevati in futuro.

Problemi correlati