«Как только деструктор вызывается для объекта, объект больше не существует, поведение не определено, если деструктор вызывается для объекта, срок жизни которого закончился»
blockquote>Проект стандарта C ++ §12.4.12
Как отмечают другие, это не означает, что реализация всегда будет делать что-то явно нежелательное (например, ошибка сегментации). Это означает, что он может делать все, что наиболее удобно.
Попытка собрать некоторое использование:
Привязка некоторого временного файла к ссылке на константу, для удлинения ее времени жизни. ссылка может быть основой - и деструктор ее не должен быть виртуальным - правильный деструктор все еще называют:
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 Alexandrescu. После того как временный файл выходит из объема, деструктор Полученных называют правильно. Вышеупомянутый код пропускает некоторые маленькие детали, но это - грандиозное предприятие с ним.
<час>константа Использования для сообщения методов других не изменит логическое состояние этого объекта.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
<час> константа Использования для классов копии на записи , чтобы заставить компилятор помочь Вам решить, когда и если не необходимо скопировать.
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
неконстанта предпочтет версию неконстанты operator[]
, и GCC создаст копию буфера резервной памяти, потому что мы могли изменить его, и это не должно влиять на данные [1 112]!
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) {
// ...
}
Существует действительно 2 основного использования константы в C++.
значения Константы
, Если значение в форме переменной, участника или параметра, который не будет (или не должен) быть измененными в течение его времени жизни необходимо отметить его константа. Это помогает предотвратить мутации на объекте. Например, в следующей функции я не должен изменяться, Студенческий экземпляр передал так, я отмечаю его константа
void PrintStudent(const Student& student) {
cout << student.GetName();
}
относительно того, почему Вы сделали бы это. Намного легче рассуждать об алгоритме, если Вы знаете, что базовые данные не могут измениться. "константа" помогает, но не гарантирует, что это будет достигнуто.
, Очевидно, печатая данные в суд не требует очень мысли :)
отмечание членского метода как константа
В предыдущем примере, я отметил Студента как константу, Но как C++ знал, что, называя GetName () метод на студенте не видоизменит объект? Ответ - то, что метод был отмечен как константа
class Student {
public:
string GetName() const { ... }
};
, отмечание метода "константа" делает 2 вещи. Прежде всего, это говорит C++, что этот метод не видоизменит мой объект. Вторая вещь состоит в том, что все членские переменные будут теперь рассматривать, как будто они были отмечены как константа. Это помогает, но не препятствует тому, чтобы Вы изменили экземпляр своего класса.
Это - чрезвычайно простой пример, но надо надеяться он поможет ответить на Ваши вопросы.
Заботьтесь для понимания различия между этими 4 объявлениями:
следующие 2 объявления идентичны семантически. Можно измениться , где ccp1 и точка ccp2, но Вы не можете изменить вещь, на которую они указывают.
const char* ccp1;
char const* ccp2;
Затем, указатель является константой, так чтобы быть значимым это должно быть инициализировано для указания на что-то. Вы не можете заставить его указать на что-то еще, однако вещь, на которую это указывает на , может быть измененной.
char* const cpc = &something_possibly_not_const;
Наконец, мы комбинируем два - таким образом, указываемая вещь не может быть изменена, и указатель не может указать на больше нигде.
const char* const ccpc = &const_obj;
по часовой стрелке правило на спирали может помочь распутать объявление http://c-faq.com/decl/spiral.anderson.html