|
Программирование >> Оптимизация возвращаемого значения
Второе отличие оператора new для массивов от оператора new для единичных объектов - это количество вызываемых конструкторов. Для создания массива необходимо вызвать конструктор для каждого его элемента: string *ps = Вызываем operator new [] для newstring[10] ; выделения памяти, способной / / хранить 10 объектов типа string, затемвызываем / / конструктор по умолчанию для каждогоэлементамассива. Аналогично, при вызове оператора delete для массива вызывается сначала деструктор для каждого элемента массива, а затем функция operator delete [ ] для освобождения памяти: delete [] ps; Вызываем деструктор string / / для каждого элемента массива, а saTeMoperatordelete[ ] / / для освобождения памяти, занятой массивом. Так же, как и функция operator delete, функция operator delete [ ] может быть переопределена или перегружена. Однако на код, перегружающий эту функцию, накладываются строгие ограничения, с которыми можно ознакомиться в книгах по языку С++ для профессиональных программистов. (См. список на стр. 287.) Операторы new и delete являются встроенными и не могут быть изменены программистом, но функции, отвечающие за выделение и освобождение памяти, модифицировать допускается. Таким образом, можно попытаться повлиять на то, как операторы new и delete выполняют свои функции, но что они при этом делают, определяется спецификациями языка. Глава 3. Исключением Введение исключений в стандарт языка С++ совершенно изменило жизнь программистов, хотя, возможно, и не в Л5шую сторону. Например, использование простых указателей стало рискованным. Увеличилось количество потенциальных источников утечки ресурсов. Стало труднее разрабатывать конструкторы и деструкторы, которые бы вели себя предсказуемым образом. Приходится принимать специальные меры, чтобы программы не останавливались внезапно во время своей работы. В целом исполняемые модули и библиотеки выросли в размерах и потеряли в производительности. И это только вершина айсберга. Сообщество С++ еще не знает о многих затруднениях, связанных с корректной разработкой программ, использующих механизм исключений. В настоящее время не существует стандартных технологий, применение которых обеспечивает предсказуемость и надежность обработки исключений. (Чтобы получить представление о некоторых проблемах, см. статью Тома Каргилла, ссылка на которую приведена на стр. 285.) Пока известно только следующее: использующие механизм исключений и при этом корректно работающие программы появляются не случайно, а требуют тщательного проектирования. Вероятность того, что не спроектированная специальным образом программа поведет себя нормально при возникновении исключения, примерно равна вероятности того, что не предназначенная для многопоточного исполнения программа будет работать в многопоточной реализации, то есть равна нулю. Если это так, зачем вообще использовать исключения? Программистам на языке С было вполне достаточно кодов ошибок еще со времен изобретения С, зачем же связываться с исключениями, если они несут столько проблем? Причина все-таки есть: исключения нельзя просто проигнорировать. Если функция сообщает о возникновении исключительной ситуации, устанавливая флаг статуса или возвращая код ошибки, то нет никакой гарантии, что модуль, вызвавший функцию, проверит этот флаг или код возврата. В результате работа программы может продолжиться, невзирая на исключительную ситуацию. Если же функция сообщает об опасной ситуации с помощью исключения, а это исключение не обрабатывается, выполнение программы тут же прекращается. Такое поведение на языке С можно смоделировать, используя функции set jmp и longjmp. Будучи перенесена в язык С++, функция longjmp приобрела один очень существенный недостаток: при выравнивании стека она не вызывает деструкторы локальных объектов. Но без вызова этих деструкторов большинство программ на языке С++ просто не будут работать, поэтому set jmp и long j mp вряд ли можно использовать вместо настоящих исгслючений. Если вам нужен метод, который позволяет отследить возникновение исключительных ситуаций и не позволяет их игнорировать, а также гарантирует вызов локальных деструкторов при просмотре стека в поисках обработчика исключительных ситуаций, то вам просто не обойтись без исключений языка С++. Поскольку вам предстоит еще многое узнать про обработку исключительных ситуаций, последующие правила представляют собой далеко не полное руководство по написанию надежного программного обеспечения. Тем не менее, они содержат важные принципы, полезные всякому, кто хочет использовать исключения в стиле языка С++. Следуя приведенным ниже рекомендациям, вы увеличите корректность, надежность и эффективность ваших программ, избежав многих ловушек, которые обычно возникают при использовании исключений. Правило 9. Чтобы избежать утечки ресурсов, используйте деструкторы Итак, попрощаемся с указателями, хотя, конечно, не со всеми. Однако указатели, используемые, например, для доступа к локальным ресурсам, нам больше не понадобятся. Предположим, что вы пишете программное обеспечение для организации, которая называется Приют милых маленьких животных и подыскивает новый дом для щенков и котят. Каждый день в организации создается файл, где перечисляются все случаи передачи питомцев в хорошие руки за день, и ваша задача - написать программу, считывающую этот файл и осуществляющую необходимую обработку данных. Разумнее всего создать базовый класс ALA (Adorable Little Animal - милое маленькое животное) и конкретные производные классы: Puppy для щенков и Kitten для котят (см. рис. 3.1). Виртуальная функция processAdoption производит необходимую обработку данных, зависящую от вида животного: Puppy ) ( Kitton Рис. 3.1 class ALA { public: virtualvoidprocessAdoption() = 0; class Puppy: public ALA ( public: virtual void processAdoption() ;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |