2015-08-10 15 views
5

Se si utilizza un riferimento const a un altro membro, è possibile che questo riferimento venga invalidato?I riferimenti const ai membri sicuri sono

class Class { 
public: 
    const int &x{y}; 
private: 
    int y; 
}; 

Ad esempio quando uso istanze di questa classe in un vettore che aumenta la sua capacità dopo un push_back. Secondo lo standard tutti gli iteratori e i riferimenti sono invalidati se un vettore deve aumentare la sua capacità. Il riferimento è ancora valido dopo?

+0

sarei sorpreso se si poteva spingere che in un vettore e hanno 'x' punto in cui si pensa lo fa. –

+0

Non dovrebbe essere sufficiente un push back per ogni istanza di 'Class' appena inserita? I dati verrebbero copiati nel vettore con x che punta alla nuova posizione y. – 0ax1

+0

Se hai preso il riferimento prima di 'push_back()', non punta a quell'elemento all'interno del vettore. 'push_back()' prende una copia. –

risposta

6

questo momento non è sicuro, come quando si copia un'istanza di Class, x farà riferimento al y dell'oggetto copiato, non proprio y. Si può vedere questo eseguendo il seguente codice:

int main() 
{ 
    Class a{}; 
    std::vector<Class> vec; 
    vec.push_back(a); 

    //these lines print the same address 
    std::cout << &(a.x) << std::endl; 
    std::cout << &(vec[0].x) << std::endl; 
} 

È possibile risolvere questo problema scrivere le proprie funzioni costruttore di copia e di assegnazione per inizializzare correttamente x:

Class (const Class& rhs) : x{y}, y{rhs.y} {} 

Questo è sicuro, perché x e y sarà distrutto solo insieme al tuo oggetto. Invalidazione di riferimenti per std::vector significa riferimenti agli elementi vettoriali:

Class c; 
std::vector<Class> vec; 
vec.push_back(c); 

Class& cr = vec[0]; 
//other operations on vec 
std::cout << c.x; //fine, that reference is internal to the class 
std::cout << cr.x; //cr could have been invalidated 
+1

Funziona ancora se sovrascrivo il copy ctor ma il vettore deve crescere dopo un push back? I riferimenti sono ancora validi? – 0ax1

+0

Sì, questo è ciò che l'ultimo paragrafo e l'indirizzo di snippet. – TartanLlama

3

Supponendo che si tratti di un riferimento a un altro membro della stessa istanza, è necessario eseguire l'override del costruttore di copie per inizializzarlo. Il costruttore di copia predefinito copia il riferimento su "y" dalla vecchia istanza che potrebbe essere invalidata.

Perché è necessario un riferimento a un membro è un'altra domanda.

P.S. inoltre è necessario ignorare un operatore di assegnazione per lo stesso motivo.

+0

Ho pensato a questo come un'alternativa al getter comune. – 0ax1

Problemi correlati