2014-05-02 14 views
10

Quanto segue sarà compile anche se una funzione membro const modificherà il valore di un membro. Come mai ?Perché i membri di riferimento possono essere modificati dalle funzioni membro const?

#include <iostream> 

struct foo 
{ 
    std::string &str; 
    foo(std::string &other) : str(other) {} 

    void operator()(std::string &some) const 
    { 
     str += some; 
    } 
}; 

int main() 
{ 
    std::string ext("Hello"); 
    foo a{ ext }; 

    std::string more(" world!"); 
    a(more); 

    cout << a.str; 
    return 0; 
} 
+5

Modifica ciò a cui fa riferimento il membro, non modifica il membro. –

+2

Perché non modificherà il riferimento stesso. Dopo aver applicato l'operatore '+ =', il riferimento non cambia, solo il contenuto della stringa interna lo fa (nel contesto della stringa, 'this' è sempre lo stesso). –

+0

Provalo con std :: string * al posto di & e vedrai la stessa cosa. – dlf

risposta

1

La const qualificazione di una funzione membro della classe indica che questa funzione utente (ad esempio, foo::operator() const) non può cambiare lo stato dell'oggetto dal punto di vista (cioè, è stato astratto) del client . Ciò non equivale esattamente a dire che i bit grezzi dell'oggetto non cambieranno.

E 'vietato ai compilatori C++ considerare gli oggetti come bit grezzi, a meno che non possano risolvere the problem of aliasing. che nel tuo caso il compilatore non può. Ciò è dovuto al fatto che esiste un alias non costante (ad esempio, std::string &str) e di conseguenza lo stato dell'oggetto è modificabile.

Cioè, chiamando operator() sull'oggetto a non cambia lo stato di a (cioè, anche se ext è cambiato, il str rimane ancora un alias ext).

Quanto sopra spiega anche perché puntare un oggetto con un puntatore a costante (ovvero, std::string * const str) non garantisce che l'oggetto non verrà modificato. Garantisce solo che l'oggetto non cambierà attraverso quel puntatore.

11

consideri il riferimento come un puntatore classico:

#include <iostream> 

struct foo 
{ 
    std::string * const str; // is the same as std::string &str 
    foo(std::string &other) : str(&other) {} 

    void operator()(std::string &some) const 
    { 
     *str += some; 
    } 
}; 

int main() 
{ 
    std::string ext("Hello"); 
    foo a{ ext }; 

    std::string more(" world!"); 
    a(more); 

    cout << a.str; 
    return 0; 
} 

Vedrai che il puntatore non cambia, solo il valore puntato da essa fa.

Problemi correlati