|
Программирование >> Операторы преобразования типа
вспомогательная функция make pair Шаблонная функция make pair() позволяет создать пару значений без явного указания типов: namespace std { Создание обьекта пары только по значениям template <class Tl. class Т2> palr<Tl. Т2> make pa1r(const T1& x. const T2& y) { return pa1r<Tl.T2>(x. y): Например, благодаря функции make pair следующие строки эквивалентны: std::makej)a1r(42,) std: .palr<lnt.char>(42. (Э) В частности, фзшкция makej3air позволяет легко передать два значения, образующие пару, функции с аргументом тина pair. Рассмотрим следующий пример: void f(std::pa1r<1nt.const char*>); void gCstd::pa1r<const int.std::string>): void foo { f(std;:niake pa1r(42. hello )); Два значения передаются в виде пары gCstd::niake pa1r(42. hello )): Два значения передаются в виде пары с преобразованием типа. Как видно из приведенного примера, функция makejDair() упрощает передачу двух значений в одном аргументе. Она работает даже при неполном соответствии типов, поскольку шаблонный конструктор обеспечивает автоматическое преобразование. Такая возможность особенно часто используется при работе с отображениями и мультиотображениями (см. с. 210). Впрочем, у выражений с явным указанием типов есть свое преимущество - они четко определяют тин полученной пары. Например, следующие два выражения дают разные результаты: std;:ра1r<1nt.f1oat>(42.7.77) std::make pa1r(42.7.77) Bo втором случае создается объект pair, у которого второй компонент относится к типу double (вещественные литералы с неуточненным типом интерпретируются как double). Тип может оказаться существенным при использовании перегруженных функций или шаблонов, в которых, например, для повышения эффективности могут быть предусмотрены разные версии для float и double. Использование функции make pair() не требует дополнительных затрат при выполнении программы. Компилятор всегда оптимизирует подобные вызовы. Примеры использования пар Тип pair часто встречается в стандартной библиотеке С++. Например, контейнеры тар и multimap используют его для операций с элементами, представляющими пары ключ/значение . Контейнеры тар и muitimap рассматриваются на с. 200. а на с. 103 приведен пример практического использования типа pair. Объекты типа pair также применяются в функциях стандартной библиотеки С++, возвращающих два значения (см. пример на с. 192). Класс auto ptr В этом разделе рассматривается тип auto ptr. Стандартная библиотека С++ предоставляет его как своего рода умный указатель , помогающий предотвратить утечки ресурсов при исключениях. Обратите внимание на слова своего рода . Они добавлены, потому что на практике применяется несколько разновидностей умных указателей. Класс auto ptr полезен только при решении определенного круга проблем. За его пределами тип auto ptr не поможет. Будьте внимательны и тщательно изучите материал этого раздела. Знакомство с классом auto ptr Функции часто работают по следующей схеме. 1. Получение ресурсов. 2. Выполнение операций. 3. Освобождение полученных ресурсов. Если полученные ресурсы связаны с локальными объектами, они автоматически освобождаются при выходе из функции в результате вызова деструкторов локальных объектов. Но если ресурсы не связаны с объектом, оии должны освобождаться явно. Как правило, такие операции с ресурсами выполняются с применением указателей. Характерный пример работы с ресурсами через указатели - создание и уничтожение объектов операторами new и delete: void f() { ClassA* ptr = new ClassA: Создание объекта Выполнение операци11 delete ptr; Уничтожение обьекта Объяснение основано на материале книги Скотта Мейерса (Scott Meyers) Моге Effective С++ . Общая схема была изначально представлена Бьярном Страуструпом под термином выделение ресурсов при инициализации в книгах The С++ Programming Language*, 2nd Edition, и The Design and Evolution of С++ . Указатель auto ptr был включен в стандарт специально для поддержки этой методики. Класс auto ptr 55 При использовании подобных схем нередко возшнсают проб.7гемы. Первая и наиболее очевидная проблема заключается в том, что программист может забыть об удалении объекта (особенно если внутри функции присутствуют команды return). Но существует и другая, менее очевидная опасность: во время работы функции может проР13ойти исключение, что приведет к немедленному выходу из функции без вьшолнения оператора delete, находящегося в конце тела функции. В результате возникает утечка памяти или, в общем случае, - ресурсов. Для ее предотвращения обычно приходится перехватывать все возможные исключения. Пример: void f() ClassA* ptr = new ClassA: Создание объекта try ( Работа с объектом catch (...){ Для произвольного исключения: delete ptr: - освободить ресурс throw; - перезапустить исключение delete ptr; Нормальное освобождение ресурса Освобождение объекта при возникновении исключений приводит к усложнению программы и появлению лишнего кода. Если по этой схеме обрабатывается не один, а два объекта или имеется несколько секций catch, программа становится еще запутаннее. В подобных решениях - сложных и чреватых ошибками - проявляется плохой стиль программирования. В данной ситуации нужен умный указатель, освобождающий данные, на которые он ссылается, при уничтожении самого указателя. Более того, поскольку такой указатель является локальной неременной, он будет уничтожаться автоматически при выходе из функции независимо от причины выхода - нормального завершения или исключения. Класс autojDtr проектировался имешю для этих целей. Указатель auto ptr является владельцем объекта, на который он ссылается. В результате уничтожение указателя автоматически приводит к уничтожению объекта. Для работы autojDtr необходимо, чтобы управляемый объект имел только одного владельца. Ниже приведен предыдущий пример, переработанный с применением auto ptr: Заголовочный файл для auto ptr Iinclude <ше[Т10гу> void fO { Создание и инициализация auto ptr std::auto ptr<ClassA> ptr(new ClassA); Работа с указателем
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |