Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> перегрузка оператора 
:(
    Опции темы
iff
Дата 12.5.2013, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Администратор
**


Профиль
Группа: Участник
Сообщений: 949
Регистрация: 23.3.2007

Репутация: нет
Всего: 16



Когда нужно использовать ссылки а когда нет?

A - это класс
Код

A operator-() const;
friend A operator-(const A&, const A&);
A& operator-=(const A&);

при это -= написан так:
Код

A& A::operator-=(const A &x) {
    return *this = *this - x;
};

может быть если возвращаемый результат ссылка (в примере с -=), то новый объект удаляется и возвращается ссыка на старый, но изменённый (return *this)?
при этом если возвращать ссылку в операторе -, то возникает предупреждение что она указывает на локальную переменную (там создаётся др. объект)


--------------------
DOS... Синей пеленой экран заполнил чистый DOS 
Мышь... Стала вдруг квадратной, потеряла форму мышь... 
Я разбил окно, девяностопятое мастдайное окно, 
И поставил DOS, и тогда увидел: Это счастье, — вот оно.  
PM MAIL WWW   Вверх
mes
Дата 12.5.2013, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(iff @  11.5.2013,  23:39 Найти цитируемый пост)
 то новый объект удаляется и возвращается ссыка на старый,

какой новый ? именно, что нового не создается, а возврашается ссылка на измененный..

Добавлено через 19 секунд
Цитата(iff @  11.5.2013,  23:39 Найти цитируемый пост)
 то возникает предупреждение что она указывает на локальную переменную (там создаётся др. объект) 

 smile 


--------------------
PM MAIL WWW   Вверх
volatile
Дата 13.5.2013, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(iff @  12.5.2013,  00:39 Найти цитируемый пост)
при это -= написан так:
A& A::operator-=(const A &x) {
    return *this = *this - x;
};

Лучше делать наоборот.
написать только оператор -=, а оператор - выражать через него.

Цитата(iff @  12.5.2013,  00:39 Найти цитируемый пост)
Когда нужно использовать ссылки а когда нет?

Цитата(iff @  12.5.2013,  00:39 Найти цитируемый пост)
A operator-() const;
friend A operator-(const A&, const A&);
A& operator-=(const A&);

Вот как у вас написано, так и нужно. (только первый, это унарный минус. он немножко здесь не к месту.)


PM MAIL   Вверх
borisbn
Дата 13.5.2013, 09:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(volatile @  13.5.2013,  00:13 Найти цитируемый пост)
написать только оператор -=, а оператор - выражать через него.

 smile как ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
math64
Дата 13.5.2013, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Лучше наверно так:
Код

class A {
public:
A operator-() const;
friend A operator-(const A&, const A&);
A& operator-=(const A&);
private:
void subtract(A& z, const A& x, const A& y);
int value;
};

A& A::operator-=(const A &x) {
    A::subtract(*this,*this, x);
    return *this;
};
A operator-(const A& x, const A&y) {
    A z;
    A::subtract(z, x, y);
    return z;
}
void A::subtract(A& z, const A& x, const A& y) {
    z.value = x.value - y.value;
}


Это сообщение отредактировал(а) math64 - 13.5.2013, 09:44
PM   Вверх
borisbn
Дата 13.5.2013, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



math64, тогда уж substract д.б. static

Это сообщение отредактировал(а) borisbn - 13.5.2013, 10:35


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 13.5.2013, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(volatile @  13.5.2013,  00:13 Найти цитируемый пост)
Лучше делать наоборот.

да и так, и так нормально. разница вкусовая (естественно, в обоих случаях можно обойтись без friend и статических функций)

Цитата(borisbn @  13.5.2013,  09:30 Найти цитируемый пост)
Цитата(volatile @  13.5.2013,  00:13 )
написать только оператор -=, а оператор - выражать через него.

  как ? 

Код

class Foo {
  public:
   Foo& operator-=(const Foo& other);
};

Foo operator-(const Foo& lhs, const Foo& rhs) {
  Foo temp(lhs);
  temp -= rhs;
  return temp;
}


Добавлено через 1 минуту и 52 секунды
кстати, см. boost::operators, там так и сделано
PM MAIL   Вверх
volatile
Дата 13.5.2013, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(baldina @  13.5.2013,  10:57 Найти цитируемый пост)
да и так, и так нормально. разница вкусовая 

не совсем вкусовая.
оператор-= более естествен, и его можно написать с меньшим оверхедом.

Цитата(iff @  12.5.2013,  00:39 Найти цитируемый пост)
A& A::operator-=(const A &x) {
    return *this = *this - x;
};

здесь создание лишнего временного экземпляра, лишний оператор присваивания, и лишнее удаление временного экземпляра.


PM MAIL   Вверх
baldina
Дата 13.5.2013, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(volatile @  13.5.2013,  13:05 Найти цитируемый пост)
оператор-= более естествен

согласен, и мне так больше нравится. но таки это вкусовой вопрос))

Цитата(volatile @  13.5.2013,  13:05 Найти цитируемый пост)
и его можно написать с меньшим оверхедом.

Код

class Foo {
  public:
   Foo& operator+=(const Foo& other);
};
Foo operator+(const Foo& lhs, const Foo& rhs) {
  Foo temp(lhs);
  temp += rhs;
  return temp;
}

vs
Код

class Foo {
  public:
   Foo operator+(const Foo& other) const;
};
Foo& operator+=(Foo& lhs, const Foo& rhs) {
  return lhs = lhs+rhs;
}

при использовании дадут практически идентичный код

Добавлено @ 14:09
тут скорее разница в том, что в случае 
Код

Foo Foo::operator+(const Foo& other) const;

может не получится неявного преобразования, требуются ужимки и прыжки
Скажем, 
Код

class Foo {
  Foo(int);
  Foo operator+(const Foo& other) const;
};
...
Foo foo0=1;
Foo foo1 = foo0+1; // ok
Foo foo2 = 1+foo0; // ups

поэтому лучше предпочитать Foo::operator+=(const Foo&);

Это сообщение отредактировал(а) baldina - 13.5.2013, 16:37
PM MAIL   Вверх
NoviceF
Дата 13.5.2013, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



Цитата(baldina @  13.5.2013,  15:01 Найти цитируемый пост)
при использовании дадут практически идентичный код

Насколько я понимаю, в первом варианте очепятка
Код

operator-


Цитата(baldina @  13.5.2013,  15:01 Найти цитируемый пост)
согласен, и мне так больше нравится. но таки это вкусовой вопрос))

Но, если верить Саттеру, 1й вариант это всётаки каноническая форма
http://programming-lang.com/ru/comp_progra...tter/0/j55.html
PM MAIL   Вверх
baldina
Дата 13.5.2013, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(NoviceF @  13.5.2013,  16:27 Найти цитируемый пост)
в первом варианте очепятка

да, исправил
Цитата(NoviceF @  13.5.2013,  16:27 Найти цитируемый пост)
Но, если верить Саттеру

Саттеру верить можно, но молиться не стоит))
PM MAIL   Вверх
baldina
Дата 13.5.2013, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



перечитал по ссылке, вижу что
1. под канонической формой он понимает взаимосвязь (в т.ч. связанное определение) operator оп() и operator оп=(). у нас это подразумевается и выполняется в обоих случаях
2. имеется упоминание неявных преобразований, о которых я упоминал
Цитата

Обратите внимание, что здесь operator@ — функция-не член, так что она обладает желательным свойством возможности неявного преобразования как левого, так и правого параметра

3. как вариант приводится и вторая форма
Цитата

T& operator@=(T& lhs, const T& rhs) {
 // ... реализация ...
 return lhs;
}

и
Цитата

В некоторых случаях (например, оператор operator*= для комплексных чисел), оператор может изменять левый аргумент настолько существенно, что более выгодным может оказаться реализация оператора operator*= посредством оператора operator*, а не наоборот.


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

Тем не менее форма с operator@= членом класса и свободной функцией operator@, реализованной через первый оператор, мне импонирует больше, т.к. позволяет меньше думать о преобразованиях и эффективности, поэтому, если не используются boost::operators, ей следует отдавать предпочтение. Не забывая, что этот вариант не является единственно правильным))
PM MAIL   Вверх
NoviceF
Дата 13.5.2013, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: нет
Всего: 2



Цитата(baldina @  13.5.2013,  18:01 Найти цитируемый пост)
В общем я принципиальных отличий от своего поста не вижу.

Так я о принципиальных отличиях и не писал smile Однако, всёже, на мой взгляд, каноническим называется именно способ реализации @ через @=, т.к.:

"В общем случае для некоторого бинарного оператора @ (+, -, * и т.д.) вы должны также определить его присваивающую версию, так чтобы a@=b и a=a@b имели один и тот же смысл (причем первая версия может быть более эффективна). Канонический способ достижения данной цели состоит в определении @ посредством @= следующим образом:.."
PM MAIL   Вверх
volatile
Дата 13.5.2013, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(baldina @  13.5.2013,  14:01 Найти цитируемый пост)
при использовании дадут практически идентичный код


baldina, в общем случае не дадут идентичный код.
я уже писал, там создание лишнего объекта, лишний оператор присваивания.
Возможности оптимизатора не безграничны. и он далеко не для всех типов может удалить конструктор, оператор присваивания и деструктор.
А для сложных типов, эти функции могут быть достаточно ресурсоемки.
Оператор+= можно написать, в большинстве случаев без создания временной переменной.
если же мы его выражаем через оператор+, то без создания временной переменной не обойтись.


Это сообщение отредактировал(а) volatile - 13.5.2013, 19:58
PM MAIL   Вверх
borisbn
Дата 14.5.2013, 06:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Господа опытные программисты, когда вы в последний раз переопределяли операторы -=() и/или -() в боевом проекте? Что это был за класс? Я, наверное, недостаточно опытный, т.к. не могу вспомнить, когда мне это было необходимо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0617 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.