Программирование >>  Обобщенные обратные вызовы 

1 ... 46 47 48 [ 49 ] 50 51 52 ... 84


ссылке, и возвращаемое значение также уже является ссылкой. Может ли он разместить копию 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



1 ... 46 47 48 [ 49 ] 50 51 52 ... 84

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика