Cercare di raccogliere alcuni usi:
Vincolare alcuni temporanei a riferimento a const, per allungarne la durata. Il riferimento può essere una base - e il suo distruttore non ha bisogno di essere virtuale - il giusto distruttore è ancora chiamato:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
Spiegazione , usando il codice:
struct ScopeGuard {
~ScopeGuard() { } // not virtual
};
template<typename T> struct Derived : ScopeGuard {
T t;
Derived(T t):t(t) { }
~Derived() {
t(); // call function
}
};
template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }
Questo trucco è usato nella classe di utilità ScopeGuard di Alexandrescu. Una volta che il temporaneo esce dal campo di applicazione, il distruttore di Derivato viene chiamato correttamente. Nel codice sopra mancano alcuni piccoli dettagli, ma questo è il grosso problema.
Usa const per dire agli altri che i metodi non cambieranno lo stato logico di questo oggetto.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
Usa const per le classi copy-on-write , per fare in modo che il compilatore ti aiuti a decidere quando e quando non devi copiarlo.
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
Spiegazione : È possibile che si desideri condividere dati quando si copia qualcosa purché i dati dell'oggetto originale e delle copie rimangano invariati. Una volta che uno degli oggetti cambia i dati, ora sono necessarie due versioni: una per l'originale e una per la copia. Cioè, si copia su una scrittura su entrambi gli oggetti, in modo che entrambi abbiano la propria versione.
Utilizzando il codice :
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Lo snippet sopra riportato stampa lo stesso indirizzo sul mio GCC, poiché la libreria C ++ utilizzata implementa una copia su scrittura std::string
. Entrambe le stringhe, anche se sono oggetti distinti, condividono la stessa memoria per i loro dati di stringa. Fare b
non const preferirà la versione non const di operator[]
e GCC creerà una copia del buffer di memoria di supporto, perché potremmo cambiarlo e non deve influenzare i dati di a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Affinché il costruttore di copie faccia copie da oggetti e provini const :
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Per creare costanti che banalmente non possono cambiare
double const PI = 3.1415;
Per il passaggio di oggetti arbitrari per riferimento anziché per valore - per impedire il passaggio di valore potenzialmente costoso o impossibile
void PrintIt(Object const& obj) {
// ...
}