Пытаюсь собрать несколько применений:
Связывание некоторого временного объекта со ссылкой на 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); }
Этот прием используется в служебном классе Александреску 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; }
};
Объяснение : Вы можете захотеть поделиться данными при копировании чего-либо, пока данные исходного и скопированного объекта остаются неизменными. Однако после того, как один из объектов изменит данные, вам понадобятся две версии: одна для оригинала и одна для копии. То есть вы копируете при записи в любой объект, так что теперь у них обоих есть собственная версия.
Используя код :
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
неконстантной версии предпочтительнее неконстантной версии, operator[]
и GCC создаст копию буфера резервной памяти, потому что мы можем изменить его, и это не должно влиять на данные a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Чтобы конструктор-копия делал копии из константных объектов и временных файлов :
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Для создания констант, которые невозможно изменить
double const PI = 3.1415;
Для передачи произвольных объектов по ссылке, а не по значению - чтобы предотвратить возможную дорогостоящую или невозможную передачу по значению
void PrintIt(Object const& obj) {
// ...
}