2013-02-14 12 views
31

Sono molto nuovo in C++ e qui c'è la mia situazione. Ho un riferimento a MyOjbect, ma l'oggetto esatto dipende da una condizione. Allora voglio fare qualcosa di simile:Come dichiarare un riferimento e inizializzarlo più tardi

MyObject& ref; 
if([condition]) 
    ref = MyObject([something]) 
else 
    ref = MyObject([something else]); 

non posso farlo in questo momento perché il compilatore non mi permette di dichiarare, ma non inizializza un punto di riferimento. Cosa posso fare per raggiungere il mio obiettivo qui?

+2

Un'inizializzazione da temporanea? Ciò non funzionerà anche senza la condizione: 'MyObject & ref = MyObject ([qualcosa]);', perché non è possibile associare un riferimento temporaneo a un valore non costante. – GManNickG

+0

@GManNickG: questo vale anche per le risposte Zaffy e suszterpatt? – qPCR4vir

+0

@ qPCR4vir: sì. La domanda rimane, in un certo senso, non direttamente. – GManNickG

risposta

30

È necessario inizializzarlo. Ma se vuoi inizializzarlo condizionatamente, puoi fare qualcosa del genere:

MyObject& ref = (condition) ? MyObject([something]) : MyObject([something else]); 
+2

Non riesco a farlo perché effettivamente faccio cose all'interno di quelle condizioni. Sono molto confuso qui. Questo mi sembra uno scenario piuttosto comune, perché non è permesso? Il mio stile di codifica è anti-C++? – user1861088

+3

@ user1861088: "Non posso farlo perché effettivamente faccio cose all'interno di quelle condizioni" Allora perché non mostri effettivamente quello che stai cercando di fare nella domanda? – GManNickG

+0

quello che intendevo dire è che eseguo più righe di codice all'interno di ogni condizione invece di chiamare semplicemente una funzione che restituisce un valore. Quindi non posso usare? : destra? – user1861088

9

In C++, non è possibile dichiarare un riferimento senza inizializzazione. È necessario inizializzarlo.

+1

Lo capisco. Quindi qualche consiglio su un walk-around? Fondamentalmente ho bisogno del riferimento in un ambito più ampio rispetto alla condizione. – user1861088

+0

@ user1861088 In tal caso, 1. ridisegnare il codice (preferito), 2. utilizzare un puntatore (non preferito). –

+1

3. non usare un riferimento, basta usare un oggetto –

8

Risposta breve: non è così.

risposta marginalmente più: fare qualcosa di simile:

MyObject& getObject() 
{ 
    if([condition]) 
     return [something] 
    else 
     return [something else]; 
} 

MyObject& ref = getObject(); 

disclaimer usuali per quanto riguarda i riferimenti si applicano naturalmente.

+0

sì ho pensato a questo ma .. è solo strano che devo fare tutto questo per raggiungere un obiettivo apparentemente semplice :( – user1861088

+0

Perché 'getObject()' restituisce un riferimento? A cosa si riferisce? –

+0

e Jonathan: che cade sotto il "solito disclaimer" bit.;) – suszterpatt

10

Non è possibile farlo. I riferimenti devono essere legati a qualcosa, potrebbe non piacerti ma impedisce un'intera classe di errori, perché se hai un riferimento puoi sempre presumere che sia legato a qualcosa, a differenza di un puntatore che potrebbe essere nullo.

Il codice di esempio non funzionerebbe comunque perché si tenta di associare un riferimento non const a un oggetto temporaneo, che non è valido.

Perché è necessario che sia comunque un riferimento? Una soluzione potrebbe essere quella di assicurare il vostro tipo ha un costruttore di default poco costoso e può essere spostato in modo efficiente, quindi basta fare:

MyObject obj; 
if([condition]) 
    obj = MyObject([something]) 
else 
    obj = MyObject([something else]); 

In caso contrario si avrebbe dovuto mettere il codice condizionale in una o più funzioni, sia:

const MyObject& ref = createObject([condition]); 

o

const MyObject& ref = [condition] ? doSomething() : doSomethingElse(); 

Si noti che entrambe queste versioni utilizzano un const di riferimento , che può legarsi ad un temporanea, se il oggetto deve essere non-const, poi di nuovo smettere di cercare di utilizzare un riferimento:

MyObject obj = createObject([condition]); 

questo sarà probabilmente essere altrettanto efficace come quello che si stava tentando di fare, grazie alla return value optimization

9

per quanto ne so questo puo' essere fatto con un riferimento Dovresti utilizzare un puntatore:

MyClass *ptr; 

if (condition) 
    ptr = &object; 
else 
    ptr = &other_object; 

Il puntatore agirà come un riferimento. Non dimenticare di usare -> per l'accesso dei membri.

+1

Puoi semplicemente dichiarare un riferimento come 'MyClass e ref = * ptr' se vuoi trasformarlo in un riferimento ... – poizan42

+0

dichiararlo come puntatore non risolverà il caso in cui il rvalore è il ritorno di una funzione –

3
MyClass *ptr; 

if (condition) 
    ptr = &object; 
else 
    ptr = &other_object; 

MyClass &ref = *ptr; 
+2

Quando rispondi , considera di scrivere una spiegazione del codice che hai scritto e questa risposta non aggiunge assolutamente nulla di nuovo alla * vecchia * domanda. – Ajean

+1

Sembra molto simile al codice di [questa risposta] (http://stackoverflow.com/a/14885051). –

+0

Mentre la mancanza di qualsiasi spiegazione è negativa, questa è comunque l'unica vera risposta che non introduce nulla di aggiuntivo o limita a ciò che può essere scritto in un operatore ternario ... – poizan42

0

È possibile utilizzare parole chiave "extern": prima volta (assumere, nel file di intestazione) è possibile dichiarare la variabile precedente dichiarazione con la parola chiave "extern". Successivamente (nel file sorgente) si ripete la dichiarazione senza "extern" e si assegna un valore.

Problemi correlati