![]() |
Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Глава 24. Перегрузка операторов 269
} Проблема в том, что в результате такого простого присвоения, как = u2 u3; , будут изменены значения и ul и и2. Чтобы избежать этого, operator+( ) должен создавать временный объект, в кото- ром и будет сохранен результат сложения. Поэтому operator + () конструирует собст- венный объект, который возвращается этой функцией. Однако при этом нельзя забывать и кое-что! Например, приведенный ниже фрагмент работать не будет.
{ unsigned cents + int dollars = cents); return result
Распространенная ошибка № 1. Хотя этот фрагмент общений об ошибке, выполнения этой функции будет весьма чевным. Проблема в том, что возвращается ссылка на объект рый является локальным для данной функции. Таким образом, к тому вре- мени, как функция сможет использовать возвращаемый результат, объект resul t уже выйдет из области видимости. Тогда почему бы нам не выделить блок памяти из кучи так, как это сделано в при- веденном ниже примере? USDollarS f in t cents + unsigned in t dollar s = dollars ; return cents) ;
Распространенная ошибка № 2, Вы, конечно, можете вернуть ссылку на объ- ект, память под который была выделена из кучи, однако возникнет новая проблема: при этом не предусматривается механизм возврата памяти в кучу. Эта ошибка называется и ее очень сложно отыскать. Хотя такой оператор и будет работать, он будет потихоньку "истощать" память в куче при каждом выполнении сложения. Возврат по значению заставляет компилятор создавать временный объект в стеке вызывающей функции. Затем созданный функцией объект копируется в этот времен- ный объект. Возникает вопрос: как долго существует временный объект, который воз- вращает operator + () ? Изначально это не было определено, однако затем создатели стандартов собрались вместе и решили, что такой временный объект остается необходимым до завершения развернутого выражения. Развернутое выражение — это все, что находится перед точкой с запятой. Рассмотрим, например, такой фрагмент:
LotsClass g 0 ; fn()
27 0 ЧастьV.Полезныеособен i; i f ! ) - g {) ) ; } Временный объект, возвращенный функцией f () , существует, пока выполняется функция д( ) и пока выполняется умножение. Там, стоит точка с запятой, этот объект уже недоступен.
operator++() В отличие от (), функция (} модифицирует свой аргумент. А значит, вам не нужно создавать временный объект или возвращать по значению. Вычисляемый результат можно хранить прямо в s. Вызывающей функции может быть возвращен предоставленный оператору аргумент. //это будет отлично работать s) {
if 100) {
}
}
ошибку.
приведенный ниже пример, который содержит одну очень хитрую
{ s.cents**; if >= 100) { cents-=100;
} return s;
Распространенная ошибка Возвращая s значению, функция застав- ляет компилятор генерировать копию объекта. Это отлично сработает в вы- ражениях типа а = но что будет с выражениями типа Мы ожидаем, что а будет увеличено на 2. Однако при приведенном выше пере- определении этого оператора, объект а будет увеличен на 1, а затем на 1 бу- дет увеличена его копия, а не сам объект а. Конструкция вида +* (*+а) не очень распространена, но все же допустима. В лю- бом случае имеется еще множество примеров, в которых такой оператор не будет ра- ботать правильно. Можно сформулировать следующее правило: если оператор изменяет значе- ние своего аргумента, возвращайте аргумент по ссылке. Если оператор не изменяет значения своих аргументов, создавайте новый объект и возвращай- те его по значению. Входные аргументы лучше всегда передавать по ссылке. |
Последнее изменение этой страницы: 2019-04-19; Просмотров: 223; Нарушение авторского права страницы