|
Программирование >> Оптимизация возвращаемого значения
static cast<EquipmentPiece*>(rawMemory); / / Создадим объекты EquipmentPiece в памяти, используя буферизованный оператор new (см. правило 8) . for (inti = 0; i<10; ++i) new(bestPieces[i]) EquipmentPiece(идентификационныйномер); Заметьте, что все еще нужно передавать аргумент в конструктор каждого объекта EquipmentPiece. Этот прием (как и использование массива указателей) позволяет создать массив объектов без конструктора по умолчанию, но не позволяет обойтись без передачи аргументов конструктору. Такого способа вообще не существует. В противном сл5Д1ае сама идея назначения конструкторов, гарантирующих инициализацию объектов, была бы скомпрометирована. У использования буферизованного оператора new есть и обратная сторона. Большинство программистов с ним вовсе не знакомо, из-за чего затруднена последующая поддержка. Но главный недостаток состоит в том, что когда время жизни объектов в массиве истечет, необходимо ъушую вызывать деструкторы этих объектов, а затем опять же вручную освободить область памяти, вызвав operator delete [ ] (снова см. правило 8): / / Уничтожаем объекты в массиве best Pieces в порядке, обратном порядку их создания, for (inti = 9; i>=0;--i) bestPieces[i].-EquipmentPiece(); Освободим область памяти. operator delete[] (rawMemory); Если забыть о данном требовании и использовать стандартный синтаксис удаления массива, то программа поведет себя непредсказуемо. Это вызвано тем, что операция удаления указателя, не инициализированного с помощью оператора new, не определена: delete [ ] bestPieces; / / Не определено!BestPieces / / не был инициализирован оператором new. Более подробная информация об операторе new, буферизованном операторе new и их взаимодействии с конструкторами и деструкторами приведена в правиле 8. Вторая проблема с классами, не имеющими конструкторов по умолчанию, -невозможность их использования со многими контейнерными шаблонами классов. Это связано с тем, что часто требуется иметь конструктор по умолчанию для параметра, с помощью которого генерируется шаблон. Это требование почти всегда вызвано тем, что внутри шаблона создается массив элементов типа параметра шаблона. Например, шаблон для класса Array может выглядеть примерно так: template<class Т> class Array{ public: Array (int size) ; private: T*data; template<class T> Array<T>::Array(int size) { data = newT[size] ; / / Вызывает T: : T для каждого элемента массива. В большинстве случаев хорошо продуманная архитектура шаблона могла бы устранить необходимость в конструкторе по умолчанию. Например, стандартный шаблон vector (он генерирует классы, которые ведут себя как массивы переменной длины) не требует, чтобы его параметр имел конструктор по умолчанию. К сожалению, архитектуру большинства шаблонов можно назвать какой угодно, только не хорошо продуманной. Из-за этого классы, не имеющие конструктора по умолчанию, оказываются несовместимыми с большинством шаблонов. Конечно, когда все программисты на С++ овладеют навыками корректного создания шаблонов, данная проблема потеряет свое значение, но как скоро это произойдет, остается только гадать. Последний аргумент в дилемме создавать или не создавать конструктор по умолчанию связан с виртуальными базовыми классами. С такими классами, если они не имеют конструкторов по умолчанию, очень сложно работать. Аргументы для конструкторов виртуального базового класса должны передаваться от самого последнего в иерархии наследующих классов. В результате виртуальный базовый класс без конструктора по умолчанию требует, чтобы все наследующие от него классы, независимо от глубины наследования, знали об аргументах конструктора виртуального базового класса, понимали их назначение и обеспечивали их передачу при вызовах. Авторы производных классов не всегда помнят об этом и не всегда оценивают по достоинству данное требование. Из-за ограничений, налагаемых на использование классов, не имеющих конструкторов по умолчанию, некоторые программисты считают, что во всех классах должны быть такие конструкторы, даже если сами конструкторы не обладают достаточной информацией для полной инициализации объекта. Например, сторонники подобной философии могли бы изменить код класса EquipmentPiece следующим образом: classEquipmentPiece{ public: EquipmentPiece (int IDNumber = UNSPECIFIED) ; private: static const int UNSPECIFIED; Особое значение, которое задается,если идентификационный номер не был указан. Этот код позволяет создавать объекты EquipmentPiece следующим образом: EquipmentPiece е; Теперь нормально. Такое изменение почти всегда усложняет реализацию других членов - функций класса, потому что нет гарантии, что поля объекта EquipmentPiece были корректно проинициализированы. Зная, что существование объекта EquipmentPiece с незаполненным идентификационным номером бессмысленно, большинство членов-функций должно будет проверять, заполнено или не заполнено данное поле. Даже если поле пусто, им нужно будет каким-то образом обработать возникшую ситуацию. Зачастую не очень понятно, как это сделать, и многие выбирают решение, не отличающееся оригинальностью: либо генерируют исключение, либо вызывают функцию, которая завершает выполнение программы. Но такое неоправданное включение в класс конструктора по умолчанию явно не ул5шает качество программы. Включение бессмысленных конструкторов по умолчанию влияет также и на эффективность работы классов. Когда члены-функции вынуждены проверять корректность инициализации полей, клиенты этих функций тратят на проверки немалое время. Код, который генерируется для проверок, и код, обрабатывающий аварийные ситуации, также увеличивает размер программ и библиотек. Подобных расходов можно избежать, если корректная инициализация полей достигается с помощью конструкторов. Но конструкторы по умолчанию часто не могут обеспечить этого, поэтому их стоит включать в программы только по очень веским причинам. Такое ограничение, накладываемое на использование классов, гарантирует, что генерируемые ими объекты будут корректно инициализированы и эффективно реализованы.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |