|
Программирование >> Обобщенные обратные вызовы
ссылке, и возвращаемое значение также уже является ссылкой. Может ли он разместить копию X или someY в памяти, доступной только для чтения? Нет, поскольку и х, и someY располагаются вне пределов функции и приходят в нее из внешнего мира и туда же возвращаются. Даже если someY динамически выделяется на лету в самой функции f, и сам объект, и владение им передается за пределы функции вызывающему коду. А что можно сказать о коде внутри функции f? Может ли ком пил я гор как-то улучшить генерируемый для тела функции f код на основе указаний const. Это приводит нас ко второму, более общему вопросу. 2. Поясните, может ли в общем случае наличие или отсутствие ключевого слова const помочь компилятору улучшить генерируемый им код и почему. Обращаясь вновь к примеру 24-1, становится очевидно, что здесь остается актуальной та же причина, по которой константность параметров не может привести к улучшению кода. Даже если вы вызываете константную функцию-член, компилятор не может полагаться на то, что не будут изменены биты объектов х или someY. Кроме того, имеются дополнительные проблемы (если только компилятор не выполняет глобальную оптимизацию). Компилятор может не знать, нет ли другого кода, в котором имеется неконстантная ссылка, являющаяся псевдонимом объектов х и/или somev, и не могут ли они быть случайно изменены через эту ссылку в процессе работы функции f. Компилятор может также не знать, объявлены ли реальные объекты, для которых X и someY являются простыми ссылками, как константные. Только того факта, что х и someY объявлены как const, не достаточно, чтобы их биты были физически константны. Почему? Поскольку любой класс может иметь шены, объявленные как mutable, или внутри функций-членов класса может использоваться приведение const cast. Даже код внутри самой функции f может выполнить приведение const cast либо преобразование типов в стиле С, что сведет на нет все объявления const. Есть один случай, когда ключевое слово const может действительно что-то значить, - это происходит тогда, когда объекты сделаны константными в точке их описания. В этом случае компилятор часто может поместить такие действительно константные объекты в память только для чтения , в особенности если это объекты POiy-, для которых их образ в памяти может быть создан в процессе ко.мпиляции и размещен в выполнимой программе. Такие объекты пригодны для размещения в ПЗУ. Как const может оптимизировать 3. Рассмотрим следующий исходный текст. Пример 24-2 void f( const z z ) { ... Ответьте на следующие вопросы. а) При каких условиях и для каких видов классов Z это конкретное указание const может помочь сгенерировать другой, лучший код? Если компилятор знает, что z - действительно константный объект, он в состоянии выполнить некоторую оптимизацию даже без глобального анализа. Например, если тело f содержит вызов наподобие g(&z), то компилятор может быть уверен, что все части z, не являющиеся mutable, не изменятся в процессе вызова д. См. пояснения о том, что такое POD, в предыдущем разделе, на стр. 159. - Прим. перев. Задача 24. Константная оптимизация 165 Однако кроме этого случая, запись const в примере 24-2 не является оптимизацией для большинства классов z, а там, где это все же приводит к оптимизации, - это уже не оптимизация генерации объектного кода компилятором. С точки зрения генерации кода компилятором вопрос в основном сводится к тому, не может ли компилятор опустить создание копии или разместить z в памяти только для чтения. То есть было бы неплохо, если бы мы знали, что z действительно не изменяется в процессе работы функции f, поскольку теоретически это означает, что мы могли бы использовать непосредственно внешний объект, передаваемый функции в качестве аргумента, без создания его копии, или, если мы все же делаем его копию, то ее можно было бы разместить в памяти только для чтения, если это дает выигрыш в производительности или желательно по каким-либо иным соображениям. В общем случае компилятор не может использовать константность параметров для устранения создания копии аргумента или предполагать побитовую константность. Как уже упоминалось, имеется слишком много ситуаций, когда данные предположения оказываются неверными. В частности, z может иметь члены, описанные как mu-tabl е, или где-то (в самой функции f, в некоторой другой функиии или в непосредственном или косвенном вызове функции-члена z) может быть выполнено приведение типов const cast или использованы какие-то другие трюки. Имеется один случай, когда компилятор способен сгенерировать улучшенный код, если: определения копирующего конструктора Z и всех функций Z, прямо или косвенно использующихся в теле функции f, видимы в данной точке; эти функции достаточно просты и не имеют побочного действия; компилятор имеет агрессивный оптимизатор. В этом случае компилятор может быть уверен в корректности своих действий и может не создавать копию объекта в соответствии с правилом, которое гласит, что компилятор может выполнять любые оптимизации, при условии, что соответствующая стандарту программа дает тс же результаты, что и без них. В качестве отступления стоит упомянуть об одной детали. Некоторые профаммисты утверждают, что есть еще один случай, когда компилятор может генерировать лучший код на основании const, а именно - при выполнении глобальной оптимизации. Дело в том, что это утверждение остается верным и в том случае, если убрать из него упоминание const. Не важно, что глобальная оптимизация все еще весьма редка и дорога; настоящая проблема заключается в том, что глобальная оптимизация использует всю имеющуюся информацию об объекте, в том числе о его реальном использовании, так что такая оптимизация работает одинаково независимо от того, объявлен ли объект как const или нет - решение принимается на основании того, что в действительности происходит с объектом, а не того, что обещает профаммист. Так что и в этом случае применение ключевого слова const ничего не дает в плане оптимизации генерируемого кода. Заметим, что несколькими абзацами ранее я сказал, что запись const в примере 24-2 не является оптимизацией для большинства классов Z и для генерации объектного кода компилятором . В оптимизаторе компилятора имеется гораздо больше возможностей, чем кажется, и в некоторых случаях const может быть полезен для некоторой реальной оптимизации. б) Говорим ли мы об оптимизации компилятором или о некотором другом типе оптимизации при условиях, рассмотренных в пункте а)? Поясните свой ответ. Например, автор Z может выполнять некоторые действия с константным объектом по-другому, написав более эффективную версию функции для случая с константным объектом. Пусть в примере 24-2 z - класс handle/body , такой как класс string с использованием подсчета ссылок для выполнения отложенного копирования. пример 24-3 void f( const Stri ng s ) { s[4]; или использование итераторов Для данного класса String известно, что вызов оператора operator[] для константного объекта string не должен приводить к изменению содержимого строки, так что можно предоставить константную перегрузку оператора operator[], которая возвращает значение типа char вместо ссылки char&: class string { ... public: const char operator char& operator ... ( size t ) const; ( size t ); Аналогично, класс String может предоставить вариант итератора consti terator, оператор operator* для которого возвращает значение типа char, а не char&. Если выполнить описанные действия и после этого воспользоваться оператором operator[] или итераторами, а переданный по значению аргумент объявлен как const, то тогда - чудо из чудес! - класс string без какой-либо дополнительной помощи, автомагичсски :) оптимизирует ваш код, устранив глубокое копирование... в) В чем состоит лучший путь достижения того же эффекта? ...но того же эффекта можно достичь, просто передавая аргумент по ссылке. Пример 24-4: более простой способ void f( const z& 2 ) { ... Этот способ работает независимо от того, использует ли объект идиому han~ ё1еД)оёу или подсчет ссылок или нет, так что просто воспользуйтесь им! > Рекомендация Избегайте передачи параметров как константных значений. Предпочтительно передавать их как ссылки на константные объекты, кроме тех случаев, когда это простые объекты наподобие int, с мизерными затратами на копирование. Резюме Вера в то, что ключевое слово const помогает компилятору генерировать более качественный код, очень распространена. Да, const действительно хорошая вещь, но основная цель данной задачи - показать, что предназначено это кгиочевое слово в первую очередь для человека, а не для компиляторов или оптимизаторов.. Когда речь идет о написании безопасного кода, const - отличный инструмент, который позволяет программистам писать более безопасный код с дополнительными проверками компилятором. Но когда речь идет об оптимизации, то const остается в принципе полезным инструментом, поскольку позволяет проектировщикам классов лучше выполнять оптимизацию вручную; но генерировать лучший код компиляторам оно помогает в гораздо меньшей степени. Задача 24. Константная оптимизация 1 67
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |