2010-11-10 12 views
8

Supponendo ho:C++ const Ivalue riferimenti

  • classe A che non è copiabile
  • classe B, che ha come membro, const A & una (e prende una A sua constructer e la imposta nella sua lista di inizializzazione)
  • una funzione A GenerateA();

questo significa che esso deve essere valido per farlo: B (GenerateA()) ?

, ad esempio, il const const significa che non viene eseguita alcuna copia di A che genera A()? E questo significa che l'ambito del temporaneo restituito viene esteso fino a quando B esiste?

EDIT: domanda Addon dai commenti: È accettabile per restituire un A & da GenerateA() per un un locale, se il valore assegnabile è un const A &?

Grazie!

+0

Non è possibile mantenere un riferimento a un valore la cui durata è stata interrotta; che è esattamente ciò che accade quando restituisci un riferimento a una variabile locale. – GManNickG

+0

@GMan: Questo era essenzialmente l'intento della mia domanda, cioè, l'uso di un riferimento const cambia la vita di detto oggetto. –

risposta

3

Come è già stato detto da altri, A GenerateA() non può compilare se A non è copiabile.

Per quanto riguarda il ref const: no, la durata della temporanea non sarà esteso alla durata di vita B. Lo standard [12.2.5] afferma:

Una temporanea legata a un membro di riferimento in un il costruttore di inizializzatore del costruttore (12.6.2) persiste fino alla chiusura del costruttore. [...] Un vincolo temporaneo al valore restituito in una dichiarazione di ritorno funzione (6.6.3) persiste fino a quando la funzione non viene chiusa.

Quindi sì, l'estensione della durata di una temporanea esiste in alcuni contesti (e talvolta è veramente utile: see this article), ma non in quello che si presentato.

Per quanto riguarda l'ultima domanda, non è legale restituire un riferimento a una variabile locale da GenerateA() (e l'associazione del risultato a un riferimento const non sarà di alcun aiuto).

+0

+1, non era al corrente di questa indennità speciale. – casablanca

0

Sì e No.

Sì, il riferimento const si legano alla variabile temporanea. No, i riferimenti const che sono membri della classe non estendono la durata nel modo in cui fanno i riferimenti const con la durata automatica.

+0

Potrebbe indicarmi la sezione pertinente nello standard? E, * non * funziona. Il compilatore (dovrebbe, gcc fa) lamentarsi della copia costruita perché l'oggetto A sia privato. –

+2

@John: ciò è dovuto al fatto che 'A' viene restituito dalla copia da' generateA() ', non dal resto del codice. Lo standard richiede un costruttore di copia accessibile (o, eventualmente, un costruttore di mosse) per chiamare 'generateA()'. –

+0

@Andre: Grazie! –

4

Se A non è copiabile, la funzione A GenerateA() non è valida poiché la restituzione di valore richiede la creazione di una copia.

Se la funzione restituisce invece un riferimento (ad esempio A &GenerateA()) e il riferimento è a un oggetto A creato in locale, diventa non valido non appena la funzione viene chiusa. C++ non ha alcuna forma di garbage collection, quindi non c'è modo di "estendere" la durata di un oggetto finché è in uso.

+0

Potresti approfondire? La copia è necessaria perché deve portare l'oggetto nello stackframe giusto? è accettabile restituire un A & da GenerateA() a un A locale, se il lvalue è un const A &? Grazie! –

+2

@John Bind: i frame di stack dipendono dall'implementazione e non influiscono sul funzionamento della lingua. La semantica del ritorno per valore è che viene creata una copia, anche se il compilatore potrebbe ottimizzarlo, è comunque un errore se l'oggetto non può essere copiato. – casablanca

+0

@casablanca: Buono a sapersi. Grazie. Punto laterale: "il compilatore potrebbe ottimizzare" == RVO? –

0

Ecco un esempio :

#include <iostream> 
using namespace std; 

int& GenX(bool reset) 
{ 
    static int* x = new int; 
    *x = 100; 
    if (reset) 
    { 
     delete x; 
     x = new int; 
     *x = 200; 
    } 
    return *x; 
} 

class YStore 
{ 
public: 
    YStore(int& x); 
    int& getX() { return my_x; } 
private: 
    int& my_x; 
}; 

YStore::YStore(int& x) 
: my_x(x) 
{ 
} 

int main() 
{ 
    YStore Y(GenX(false)); 
    cout << "X: " << Y.getX() << endl; 
    GenX(true); // side-effect in Y 
    cout << "X: " << Y.getX() << endl; 
    return 0; 
} 

uscita:

X: 100 
X: 200 
+1

Ciò annulla lo scopo dell'utilizzo di un riferimento e crea una perdita di memoria. – casablanca

+1

Questo è un codice errato. – GManNickG

+0

Abusa la lingua, si. –