| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > перегрузка оператора |
| Автор: iff 12.5.2013, 00:39 | ||||
| Когда нужно использовать ссылки а когда нет? A - это класс
при это -= написан так:
может быть если возвращаемый результат ссылка (в примере с -=), то новый объект удаляется и возвращается ссыка на старый, но изменённый (return *this)? при этом если возвращать ссылку в операторе -, то возникает предупреждение что она указывает на локальную переменную (там создаётся др. объект) |
| Автор: volatile 13.5.2013, 00:13 | ||||
Лучше делать наоборот. написать только оператор -=, а оператор - выражать через него.
Вот как у вас написано, так и нужно. (только первый, это унарный минус. он немножко здесь не к месту.) |
| Автор: borisbn 13.5.2013, 09:30 |
| Автор: math64 13.5.2013, 09:42 | ||
Лучше наверно так:
|
| Автор: borisbn 13.5.2013, 10:35 |
| math64, тогда уж substract д.б. static |
| Автор: baldina 13.5.2013, 10:57 | ||||
да и так, и так нормально. разница вкусовая (естественно, в обоих случаях можно обойтись без friend и статических функций)
Добавлено через 1 минуту и 52 секунды кстати, см. http://www.boost.org/doc/libs/1_53_0/libs/utility/operators.htm, там так и сделано |
| Автор: volatile 13.5.2013, 13:05 |
не совсем вкусовая. оператор-= более естествен, и его можно написать с меньшим оверхедом. здесь создание лишнего временного экземпляра, лишний оператор присваивания, и лишнее удаление временного экземпляра. |
| Автор: baldina 13.5.2013, 14:01 | ||||||||
согласен, и мне так больше нравится. но таки это вкусовой вопрос))
vs
при использовании дадут практически идентичный код Добавлено @ 14:09 тут скорее разница в том, что в случае
может не получится неявного преобразования, требуются ужимки и прыжки Скажем,
поэтому лучше предпочитать Foo::operator+=(const Foo&); |
| Автор: NoviceF 13.5.2013, 16:27 | ||||
Насколько я понимаю, в первом варианте очепятка
Но, если верить Саттеру, 1й вариант это всётаки каноническая форма http://programming-lang.com/ru/comp_programming/satter/0/j55.html |
| Автор: baldina 13.5.2013, 16:37 |
да, исправил Саттеру верить можно, но молиться не стоит)) |
| Автор: baldina 13.5.2013, 17:01 | ||||||
| перечитал по ссылке, вижу что 1. под канонической формой он понимает взаимосвязь (в т.ч. связанное определение) operator оп() и operator оп=(). у нас это подразумевается и выполняется в обоих случаях 2. имеется упоминание неявных преобразований, о которых я упоминал
3. как вариант приводится и вторая форма
и
В общем я принципиальных отличий от своего поста не вижу. Думаю, еще надо учесть, что писалось это 10лет назад, с тех пор оптимизаторы несколько ушли вперед (например хорошо научились делать NRVO), и некоторые соображения эффективности уже не играют существенной роли. Тем не менее форма с operator@= членом класса и свободной функцией operator@, реализованной через первый оператор, мне импонирует больше, т.к. позволяет меньше думать о преобразованиях и эффективности, поэтому, если не используются boost::operators, ей следует отдавать предпочтение. Не забывая, что этот вариант не является единственно правильным)) |
| Автор: NoviceF 13.5.2013, 18:57 |
Так я о принципиальных отличиях и не писал "В общем случае для некоторого бинарного оператора @ (+, -, * и т.д.) вы должны также определить его присваивающую версию, так чтобы a@=b и a=a@b имели один и тот же смысл (причем первая версия может быть более эффективна). Канонический способ достижения данной цели состоит в определении @ посредством @= следующим образом:.." |
| Автор: volatile 13.5.2013, 19:56 |
baldina, в общем случае не дадут идентичный код. я уже писал, там создание лишнего объекта, лишний оператор присваивания. Возможности оптимизатора не безграничны. и он далеко не для всех типов может удалить конструктор, оператор присваивания и деструктор. А для сложных типов, эти функции могут быть достаточно ресурсоемки. Оператор+= можно написать, в большинстве случаев без создания временной переменной. если же мы его выражаем через оператор+, то без создания временной переменной не обойтись. |
| Автор: borisbn 14.5.2013, 06:00 |
| Господа опытные программисты, когда вы в последний раз переопределяли операторы -=() и/или -() в боевом проекте? Что это был за класс? Я, наверное, недостаточно опытный, т.к. не могу вспомнить, когда мне это было необходимо. |
| Автор: bsa 14.5.2013, 08:00 |
| Я это делал, когда писал с++ обертку для bigdigits. В принципе, переопределение данного операторов (да и всех математических) имеет смысл только для матемаических классов. |
| Автор: baldina 14.5.2013, 10:06 | ||||
не так часто, конечно)) обычно алгебра, bsa прав из последних - классы математических выражений для отображения хода вычислений, года три назад. давно как-то приходилось вектора/матрицы писать Добавлено через 6 минут и 44 секунды еще (довольно давно) были классы для вычислений с учетом размерностей иногда возникают небольшие задачи с использованием operator+ специального вида для строк (вроде конкатенации с добавлением разделителя) Добавлено через 10 минут и 21 секунду пара
по идее должны давать одинаковый код при любой реализации. конечно, это от самих классов и компилятора зависит... давайте проведем эксперимент: предлагайте (разумную) семантику operator+() в конкретном, гипотетически полезном случае - сравним |
| Автор: bsa 14.5.2013, 14:30 | ||
Обычно, оператор + реализуется через +=:
|
| Автор: volatile 14.5.2013, 17:45 | ||||||||
Ну хорошо. Давайте, чтоб не скучно было, выведем первую тыщу чисел фибоначчи. Код конечно далёк от оптимального, (например. в чаре храницца только число в диапазоне [0..9], ну да суть не в этом.
Будем подсчитывать кол-во созданных объектов big_num, потребовавшихся для вычисления. в первом варианте (BALDINA_VARINT) сорри за имя 'BALDINA_VARINT', что-то ничего больше не пришло больше в голову. переименуйте как вам угодно.
На gcc и в студии одинаково. В студии была максимальная оптимизация на скорость + Use Link Time Code Generation Добавлено через 7 минут и 6 секунд Попробовал на codepad.org. Тыщу чисел он не смог переварить, уменьшил в 10 раз http://codepad.org/02MJuOJS http://codepad.org/Ol4LplTE objects: 202 objects: 102 но там без оптимизации. На домашнем компе objects: 102 objects: 52 В любом случае разница в 2 раза количества объектов сохраняецца. |
| Автор: baldina 15.5.2013, 14:05 | ||||
| да, все верно пример мог быть и попроще, если деструкторами измерять, доп объект всегда присутствует. кстати, вариант со свободной функцией operator+(), некоторыми компиляторами оптимизируется хуже, чем с членом класса. интересно, что (в данном конкретном случае), компилятор таки умудряется обходиться без фактического "лишнего копирования":
здесь от временного объекта только один след - изменение деструктором object_counter сравните с явно определенным operator=()
|
| Автор: bsa 15.5.2013, 15:18 |
| К сожалению, вариант с членом класса менее гибок. Например, если суммируются объекты разных типов, но один из них может быть неявно создан из второго (конструктор соответствующий есть). То в этом случае вариант с внешним оператором будет поддерживать и a+b, и b+a, а вот вариант со встроенным - только a+b. |
| Автор: volatile 15.5.2013, 18:50 | ||||
кол-во деструкторов == равно кол-ву констукторов == кол-ву объектов. деструкторами измерялось только в силу удобства определения в одном месте. Хорошо, хотя это не совсем корректно по сравнению с кол-вом объектов.
Тем не менее, операторов присваивания, как и деструкторов в 2 раза больше:
|
| Автор: bsa 15.5.2013, 20:21 | ||
Кстати, оператор присваивания рекомендуется делать через операцию swap.
|
| Автор: volatile 15.5.2013, 23:41 | ||||||
bsa, чтоб делать через swap, нужно сначала написать этот swap И кстати, даже если решицца писать его, то для данного конкретного класса, swap априори будет менее эффективен чем memcpy. Так что слепо следовать рекомендациям, далеко не всегда оправдано.
baldina, в общем как я понял, вы хотите сказать, что не смотря на разницу в количестве объектов, операторов присваивания, деструкторов и прочих сишних прибамбасов, компилятор, каким-то неведомым, волшебным способом делает так, что код, всё равно выполняецца за одинаковое время... Ну чтож, давайте (чтоб уже добить тему) измерим и время... Время в миллионах тиков процессора. (по 3 измерения на каждый вариант) Первый вариант
Второй вариант
Весь проект для 2008-ой студии (без бинарников). |
| Автор: bsa 16.5.2013, 18:42 |
| Да. Не обратил внимания. Обычно, такое через динамические массивы делают. |
| Автор: baldina 17.5.2013, 12:10 |
| Доберусь до компа, погляжу. Да, я имел в виду что в частных случаях (частых для математических классов) результат может быть одинаков за счет оптимизации. В общем конечно нет, если требуется вызывать сложные конструкторы/деструкторы Как уже говорил, я сам за каноническую форму, просто хотелось побудить к размышлению и расставить все точки. |