Главная » Просмотр файлов » Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003)

Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769), страница 79

Файл №1160769 Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003)) 79 страницаД. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769) страница 792019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 79)

Продемонстрируем это на примере. фпад б1(1пг сопев й г) ( гесигп ++ (1пга) г; // Нерационально, но законно ) 1пс б2(1пг сопит а г) ( гегигп г; 1пс бЗ () ( гесигп 42; ) 1пг Йоо() ( 1пг рагим = О; 1пс апзмег = О; апзыег = б1(рагащ)з б2(рагащ); НЗ (); гесигп апзыег + рагат; Функция б1 ( ) содержит аргумент типа сопзг 1пс, который передается по ссылке. Обычно это означает, что объект, который передается в функцию, не модифицируется в ней.

Однако, если значение передаваемой величины поддается изменению, в программе на С++ молификатор сопит может быть законным путем отменен, а значение величины — модифицировано. (Можно возразить, что так делать неразумно, однако стандарт 440 Глава 22. Объекты-функции и обратные вызовы С++ допускает подобные операции.) Именно это и происходит в функции б1 ( ) . В силу вышесказанного компилятор, оптимизирующий сгенерированный код в пределах каждой функции (по такому принципу работает большинство компиляторов), должен учитывать, что в любой функции, в которую передаются ссылки или указатели иа объект, этот объект может быть изменен. При этом нужно учесть, что в общем случае компилятору доступна информация только об обьявлеиии функции, поскольку ее определеиие (или реализаг(ил) часто находится в другой единице трансляции.

Таким образом, в приведенном выше примере большинство компиляторов предполагают, что в функции й2() переменная рагаш тоже может быть модифицирована (иесмотря иа то, что иа самом деле это ие так). Фактически компилятор даже ие может предполагать, что функция ЕЗ ( ) ие модифицирует локальную переменную рагага Действительно, ведь у функций й1() и б2 () во время их вызова была возможность сохранить адрес этой переменной в глобально доступном указателе. Поэтому с точки зрения компилятора обладающего неполными сведениями, нет ничего невозможного в том, что в функции' йЗ () значение переменной рагагв будет изменено с помощью этого глобального указателя.

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

Однако зто достигается за счет уменьшения скорости компиляции, увеличения расхода ресурсов и снижения степени надежности полученного кода. Проекты, иа компиляцию которых с помощью обычных компиляторов потребовалось бы несколько минут, в таких системах компилируются несколько часов, а иногда и дней (при условии, что в распоряжении компилятора имеется несколько гигабайт памяти). Более того, компиляторы, о которых идет речь, как правило, намного сложнее, чем обычные, поэтому вероятность генерации неправильного кода в иих выше.

Даже если компилятор с повышенной степенью оптимизации сгеиерирует правильный код, в исходном коде могут содержаться непреднамеренные нарушения запутанных правил использования псевдонимов в языках программирования С и С++ . При г обычной оптимизации такие нарушения могут оказаться вполне безобидными, ио при улучшенной оптимизации оии превращаются в ошибки. Однако значительную помощь обычным оптимизаторам может оказать процесс встраивания функций. Предположим, что функции й1 (), 22 () и ЕЗ () обьявлены как встраиваемые. В этом случае компилятор преобразует код функции боо () таким образом, что ои будет эквивалентен приведенному ниже. г В качестве примера такой ошибки можно привести попытку доступа к переменной типа ппвгчпед 1пе с помощью обычного указателя нв ьпе (со знаком).

22.2. Указатели и ссылки на функции з.пс Йоо' () ( 1пс рагагп = Ор зпг апвыег = О; апвыег = ++(зппй)ракет; геТпгп апвьгег + рагаш; Даже обычный оптимизатор способен преобразовать этот код в следующий: з,пс йоо' ' () ( гесигп 2; Из этого примера видно, что преимущество использования встраиваемых функций не только в том, что они помогают избежать выполнения машинного кода, в котором вызывается последовательность функций, но и в том (и зачастую это важнее), что благодаря им оптимизатор получает информацию о процессах, происходящих с переменными, которые передаются в функции.

Причем же тут шаблоны? Скоро вы убедитесь, что с их помошью иногда можно организовать обратные вызовы, в процессе компиляции которых генерируется код, включающий в себя прямые, а иногда даже встраиваемые вызовы, в то время как обычные обратные вызовы привели бы к использованию косвенных вызовов. При этом можно достичь существенного повышения производительности работы полученного исполняемого файла 22.2.

Указатели и ссылки на функции Рассмотрим приведенное ниже довольно простое определение функции йоп ( ) . 'ехкегп "С++" чозс) йоо() с)тгоы() ( ) Можно было бы охарактеризовать тип этой функции как "функция без аргументов со связыванием С++, которая не возвращает значений и не генерирует исключений". По историческим причинам в формальном определении функции в языке С++ спецификация исключения не входит в описание типа функции . Однако в будущем ситуация может изз мениться. В любом случае разумно при создании новых функций указывать их спецификации исключений. Связывание имен (обычно "С" и "С++") представляет собой, по сути, часть типа, но во многих реализациях языка С++ это условие соблюдается недостаточно строго.

В частности, в таких системах вполне допустимо указателю на функцию со з Исторические причины этого ие совсем понятны, и в данной области стандарт С++ несколько непоследователен. Глава 22. Объекты-функции и обратные вызовы 442 связыванием С присваивать значение указателя на функцию со связыванием С++ и наоборот.

Это следствие того, что в большинстве платформ соглашения о вызовах, применимые для функций С и С++, идентичны, если эти функции обладают одинаковым подмножеством параметров и возвращают значения одних и тех же типов. В большинстве ситуаций выражение йоо неявным образом преобразуется в указатель на функцию йоо(). Заметим, что сам идентификатор йоо не является обозначением указателя, точно так же, как выражение йа после объявления 1пг Та[10); не обозначает указатель на массив (или на его первый элемент). Такое неявное преобразование функции (или массива) в указатель часто называют сведением (десау). Чтобы проиллюстрировать это преобразование, рассмотрим завершенную программу на С++, которая приведена ниже.

// Ецпсгогв/йипсрсг.срр $1пс1цде <1озггеат> $1пс1ис)е <суре1п/ро> уойг) Еоо() ( зМ: ."соцс « "Еоо() са11ед" «зсс)::епд1; ) сурейей уо1с) РооТ()/ // РооТ вЂ” это тип функции, // совпадающий с типом функции йоо() йпг пайп() ( Йоо() р // Прямой вызов // Вывод типов йоо и РооТ згс)::соус « "Турез об йоо: " « СуреЫ[йоо].паве() « '~п'; зМ::сонг « "Турез ой РооТ: " « Гуре16(РооТ].пал1е() « '1п'; РооТ* рб = йоо/ // Неявное преобразование (сведение); И() ' // косвенный вызов с помощью указателя; (*рй)(); // эквивалент вызова рй(] // Вывод типа указателя рй зсг)::соис « "турез ой рй: " « суреЫ(рй).пате() « '1п'; Роста гб = йоса // Веэ неявного преобразования; 22.2.

Указатели и ссылки на функции // косвенный вызов по ссылке кй (); // Вывод типа гй вас)::ссис « "Турев об кб: " « пуре16(гй).паве() « '~п'; Эта функция демонстрирует разнообразные варианты использования типов функций, включая некоторые не совсем необычные. В рассмотренном примере используется оператор суреЫ, возвращающий статический тип вес):: суре 3 пйо, функция паве () которого выводит типы некоторых выражений (см. раздел 5.6, стр. 79). Когда оператор суреэ'.6 применяется к типу функции, сведения типа не происходит.

Ниже приведен вывод рассматриваемой демонстрационной программы, скомпилированной с помощью одного из компиляторов С++. йоо () Турев Туре в йоо () Тоо () Турев бсо () Турев са12ес( о~ й: чозс(() об йооТ: чозс)() са11ес) са11ес1 ой рй: РооТ * са11ес) об кб: чоЫ() Как видите, в этом компиляторе определения типов имен сохраняются в том виде, в котором они возвращаются функцией паве () (например, вместо расширенной формы типа чойс( (*) () выводится тип РооТ *), однако зто не является требованием языка и в других компиляторах может не выполняться. В этом примере также показано, что ссылки на функции существуют как концепция языка, но вместо них почти всегда используются указатели на функции (чтобы избежать неоднозначности, по-видимому, лучше всего продолжать использовать именно их).

Обратите внимание, что на самом деле выражение боо — это так называемое 1-значение (1ча1ие), поскольку его можно связать со ссылкой на неконстантный тип. Однако модифицировать данное 1ча1ие невозможно. Заметим, что имя указателя нв функцию (например, рб) или имя ссылки на функцию (например, кТ) можно использовать точно так же, как и имя самой функции. Таким образом, указовель на функцию — это функтор, т.е. такой обьект, который при вызове функции может быть использован вместо ее имени. С другой стороны, поскольку ссылка — это не объект, ссылка на функцию функтором не является. Если вспомнить описанные ранее особенности прямых и косвенных вызовов, то станет понятно, что использование этих идентичных обозначений может привести к значительным различиям в производительности программы.

Глава 22. Объекты-функции и обратные вызовы 22.3. Указатели на функции-члены Чтобы понять, чем различаются указатели на обычные функции и указатели на функции-члены, полезно разобраться, как происходит вызов функции-члена в типичной реализации С++.

Характеристики

Тип файла
DJVU-файл
Размер
5,6 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6508
Авторов
на СтудИзбе
302
Средний доход
с одного платного файла
Обучение Подробнее