C++ (Хилл, Страуструп) - страница 107

void g(int a) (* static table t(a); // ошибка *)

Традиционно выполнением программы считалось выполнение main(). Так никогда не было, даже в C, но только размещение статических объектов класса с конструктором и/или деструктром дают программисту простой и очевидный способ задания тго, что будет выполняться до и/или после вызова main().

Вызов конструкторов и деструкторов для статических обектов играет в С++ чрезвычайно важную роль. Это способ обеспечить надлежащую инициализацию и очистку структур данных в библиотеках. Рассмотрим «stream.h». Откуда берутся cin, cout и cerr? Где они получают инициализацию? И, что самое главное, поскольку потоки вывода имеют внутренние буферы сиволов, как же эти буферы заполняются? Простой и очевидный овет таков, что эта работа осуществляется соответствующими конструкторами и деструкторами до и после выполнения main(). Для инициализации и очистки библиотечных средств есть возмоности, альтернативные использованию конструкторов и деструторов. Все они или очень специальные, или очень уродливые.

Если программа завершается с помощью функции exit(), то деструкторы для статических объектов будут вызваны, а если она завершается с помощью abort(), то не будут. Заметьте, что это подразумевает, что exit() не завершает программу мгновено. Вызов exit() в деструкторе может привести к бесконечной рекурсии.

Иногда, когда вы разрабатываете библиотеку, необходимо или просто удобно создать тип с конструктором и деструктором, предназначенными только для одного: инициализировать и очитить. Такой тип обычно используется только с одной целью, для размещения статического объекта так, чтобы вызывались контруктор и деструктор.

5.5.3 Свободная Память

Рассмотрим:

main() (* table* p = new table(100); table* q = new table(200); delete p; delete p; // возможно, ошибка *)

Конструктор table::table() будет вызван дважды, как и деструктор table::~table(). То, что С++ не дает никаких грантий, что для объекта, созданного с помощью new, когда-либо будет вызван деструктор, ничего не значит. В предыдущей прорамме q не уничтожается, а p уничтожается дважды! Программист может счесть это ошибкой, а может и не счесть, в зависимости от типа p и q. Обычно то, что объект не уничтожается, являеся не ошибкой, а просто лишней тратой памяти. Уничтожение p дважды будет, как правило, серьезной ошибкой. Обычно резултатом применения delete дважды к одному указателю приводит к бесконечному циклу в подпрограмме управления свободной пмятью, но определение языка не задает поведение в таком слчае, и оно зависит от реализации.