Спроба зібрати деякі використання:
Прив’язання деякого тимчасового до посилання на const, щоб продовжити його термін експлуатації. Посилання може бути базовим - і деструктор не повинен бути віртуальним - правильний деструктор все ще називається:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
Пояснення з використанням коду:
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); }
Цей трюк використовується в утилітному класі Alexandrescu ScopeGuard. Як тільки тимчасове виходить із сфери дії, деструктор Derived викликається правильно. У наведеному вище коді відсутні деякі дрібні деталі, але це велика справа.
Використовуйте const, щоб сказати іншим методам, не змінить логічний стан цього об'єкта.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
Використовуйте const для класів "копіювати при записі" , щоб компілятор допоміг вам вирішити, коли і коли не потрібно копіювати.
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
Пояснення . Можливо, ви хочете поділитися даними, коли копіюєте щось, доки дані оригіналу та об'єкта copie'd залишаються однаковими. Після того, як один із об’єктів змінює дані, тепер вам потрібні дві версії: одна для оригіналу та одна для копії. Тобто, ви скопіювати на записи або об'єкт, так що тепер вони обидва мають свою власну версію.
Використання коду :
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Вищенаведений фрагмент друкує ту саму адресу на моєму GCC, тому що використана бібліотека C ++ реалізує копіювання під час запису std::string
. Обидва рядки, навіть якщо це окремі об'єкти, мають однакову пам'ять для своїх рядкових даних. Якщо зробити b
non-const, то віддасть перевагу non-const версії operator[]
та GCC створить копію буфера резервної пам'яті, тому що ми могли б її змінити, і це не повинно впливати на дані a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Конструктор копій може робити копії з const-об'єктів і тимчасових періодів :
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Для створення констант, які тривіально не можуть змінитися
double const PI = 3.1415;
Для передачі довільних об'єктів за посиланням, а не за значенням - для запобігання можливого дорогого або неможливого передачі по вартості
void PrintIt(Object const& obj) {
// ...
}