Próbuję zebrać kilka zastosowań:
Powiązanie niektórych tymczasowych z odniesieniem do const, aby wydłużyć jego żywotność. Odniesienie może być bazą - a jego destruktor nie musi być wirtualny - właściwy destruktor jest nadal nazywany:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
Wyjaśnienie za pomocą kodu:
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); }
Ta sztuczka jest używana w klasie narzędziowej ScopeGuard Alexandrescu. Gdy obiekt tymczasowy znajdzie się poza zakresem, Destruktor klasy Derived jest wywoływany poprawnie. W powyższym kodzie brakuje kilku drobnych szczegółów, ale to jest wielka sprawa.
Użyj const, aby powiedzieć innym metodom, że nie zmienią stanu logicznego tego obiektu.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
Użyj const dla klas kopiowania przy zapisie , aby kompilator pomógł ci zdecydować, kiedy nie chcesz kopiować.
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
Objaśnienie : Możesz chcieć udostępniać dane podczas kopiowania, o ile dane obiektu oryginalnego i kopiowanego pozostają takie same. Gdy jeden z obiektów zmieni dane, potrzebujesz teraz dwóch wersji: jednej dla oryginału i jednej dla kopii. Oznacza to, że kopiowanie na zapis do obu obiektów, tak, że teraz obie mają własną wersję.
Używając kodu :
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Powyższy fragment kodu wyświetla ten sam adres na moim GCC, ponieważ używana biblioteka C ++ implementuje kopiowanie przy zapisie std::string
. Oba łańcuchy, mimo że są odrębnymi obiektami, współużytkują tę samą pamięć dla swoich danych. Utworzenie wartości b
innej niż const będzie preferować wersję operator[]
inną niż const, a GCC utworzy kopię zapasowego bufora pamięci, ponieważ możemy go zmienić i nie może to wpływać na dane a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Aby konstruktor kopiujący mógł wykonać kopie z obiektów stałych i tymczasowych :
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Do tworzenia stałych, których trywialnie nie można zmienić
double const PI = 3.1415;
Do przekazywania dowolnych obiektów przez odniesienie zamiast według wartości - aby zapobiec potencjalnie kosztownemu lub niemożliwemu przekazywaniu wartości bocznej
void PrintIt(Object const& obj) {
// ...
}