Ответ 1
Попытка собрать некоторые виды использования:
Связывание некоторого временного ссылки на-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 для классов copy-on-write, чтобы компилятор помог вам решить, когда и когда вам не нужно копировать.
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, потому что используемая библиотека С++ реализует copy-on-write std::string
. Обе строки, даже если они являются отдельными объектами, используют одну и ту же память для своих строковых данных. Создание b
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) {
// ...
}