Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:02
Оценка:
Допустим, есть объект, для которого надо реализовать оператор +.
Как это лучше всего сделать?

— возвращать его по значению (но тогда ведь будет происходить копирование и копирующее присваивание)
— возвращать указатель на него (но тогда прийдётся записывать выражение для указателей, а не для объектов, типа
pA = pB + pC вместо a = b + c)
— возвращать ссылку на динамическую переменную (но как тогда пользователь догадается о необходимости уничтожения?)

И вообще, напишите, что конкретно будет происходить, а также что должно быть выполнено до и после конструкции
a = b + c.

Сразу ли результат будет положен в a, или сначала он будет вычислен, а потом будет применён оператор =?
В общем, распишите подробнее...
Re: Большие объекты и операторы.
От: LaptevVV Россия  
Дата: 20.10.04 16:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Допустим, есть объект, для которого надо реализовать оператор +.

А>Как это лучше всего сделать?

А>- возвращать его по значению (но тогда ведь будет происходить копирование и копирующее присваивание)

А>- возвращать указатель на него (но тогда прийдётся записывать выражение для указателей, а не для объектов, типа
А>pA = pB + pC вместо a = b + c)
А>- возвращать ссылку на динамическую переменную (но как тогда пользователь догадается о необходимости уничтожения?)

А>И вообще, напишите, что конкретно будет происходить, а также что должно быть выполнено до и после конструкции

А>a = b + c.

А>Сразу ли результат будет положен в a, или сначала он будет вычислен, а потом будет применён оператор =?

А>В общем, распишите подробнее...
Если большой объект — контейнер, то на эту тему можно прочитать по крайней мере в двух книжках:
1. Джосаттис и Вандевурд. Шаблоны в С++
2. Брюс Эккель. Философия С++.
Тема называется " шаблоны выражений" и относится к метапрограммированию на С++. Тема сложная, поэтому так просто объяснить — не получится. Если просто реализовывать операции — получается не очень эффективно из-за постоянного создания и уничтожения временных объектов.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:11
Оценка:
И ещё вопрос:

корректно ли так:

T& fun(T& a, T& b)
{
   T c;
   ...
   return c;
}
Re[2]: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:13
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Аноним, Вы писали:


А>>Допустим, есть объект, для которого надо реализовать оператор +.

А>>Как это лучше всего сделать?

А>>- возвращать его по значению (но тогда ведь будет происходить копирование и копирующее присваивание)

А>>- возвращать указатель на него (но тогда прийдётся записывать выражение для указателей, а не для объектов, типа
А>>pA = pB + pC вместо a = b + c)
А>>- возвращать ссылку на динамическую переменную (но как тогда пользователь догадается о необходимости уничтожения?)

А>>И вообще, напишите, что конкретно будет происходить, а также что должно быть выполнено до и после конструкции

А>>a = b + c.

А>>Сразу ли результат будет положен в a, или сначала он будет вычислен, а потом будет применён оператор =?

А>>В общем, распишите подробнее...
LVV>Если большой объект — контейнер, то на эту тему можно прочитать по крайней мере в двух книжках:
LVV>1. Джосаттис и Вандевурд. Шаблоны в С++
LVV>2. Брюс Эккель. Философия С++.
LVV>Тема называется " шаблоны выражений" и относится к метапрограммированию на С++. Тема сложная, поэтому так просто объяснить — не получится. Если просто реализовывать операции — получается не очень эффективно из-за постоянного создания и уничтожения временных объектов.

Да, контейнер...
А вообще, есть идея оставить только +=, -=, *=, чтобы хотя бы было ясно, что происходит
Re[2]: Большие объекты и операторы.
От: LaptevVV Россия  
Дата: 20.10.04 16:14
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>И ещё вопрос:


А>корректно ли так:


А>
А>T& fun(T& a, T& b)
А>{
А>   T c;
А>   ...
А>   return c;
А>}
А>

Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:29
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Аноним, Вы писали:


А>>И ещё вопрос:


А>>корректно ли так:


А>>
А>>T& fun(T& a, T& b)
А>>{
А>>   T c;
А>>   ...
А>>   return c;
А>>}
А>>

LVV>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.
А как тогда реализуются операторы для больших объектов, возвращающие ссылки?
Re[4]: Большие объекты и операторы.
От: LaptevVV Россия  
Дата: 20.10.04 16:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, LaptevVV, Вы писали:


LVV>>Здравствуйте, Аноним, Вы писали:


А>>>И ещё вопрос:


А>>>корректно ли так:


А>>>
А>>>T& fun(T& a, T& b)
А>>>{
А>>>   T c;
А>>>   ...
А>>>   return c;
А>>>}
А>>>

LVV>>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.
А>А как тогда реализуются операторы для больших объектов, возвращающие ссылки?
1. функция может вернуть ссылку, если она ее получила как параметр
2. можно вернуть ссылку на статическую переменную
3. можно вернуть ссылку на динамическую переменную — только пример попроси привести действующих програмистов — у меня под рукой нет, а они на практивке это делают.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:38
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>>>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.

А>>А как тогда реализуются операторы для больших объектов, возвращающие ссылки?
LVV>1. функция может вернуть ссылку, если она ее получила как параметр
LVV>2. можно вернуть ссылку на статическую переменную
LVV>3. можно вернуть ссылку на динамическую переменную — только пример попроси привести действующих програмистов — у меня под рукой нет, а они на практивке это делают.
В конкретном примере нужно вернуть ссылку на некоторый новый объект.
1 — не подходит,
3 — тогда вряд ли будет выглядеть красивым delete &с где-то в программе.
Остаётся второе.
А вообще, в таких случаях это хорошо?
Re[6]: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 16:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, LaptevVV, Вы писали:


LVV>>>>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.

А>>>А как тогда реализуются операторы для больших объектов, возвращающие ссылки?
LVV>>1. функция может вернуть ссылку, если она ее получила как параметр
LVV>>2. можно вернуть ссылку на статическую переменную
LVV>>3. можно вернуть ссылку на динамическую переменную — только пример попроси привести действующих програмистов — у меня под рукой нет, а они на практивке это делают.
А>В конкретном примере нужно вернуть ссылку на некоторый новый объект.
А>1 — не подходит,
А>3 — тогда вряд ли будет выглядеть красивым delete &с где-то в программе.
А>Остаётся второе.
А>А вообще, в таких случаях это хорошо?

Мне кажется, что нехорошо... ведь в памяти может повиснуть в результате куча статических переменных.
Re: Большие объекты и операторы.
От: korzhik Россия  
Дата: 20.10.04 17:02
Оценка: 11 (4)
Здравствуйте, Аноним, Вы писали:

А>Допустим, есть объект, для которого надо реализовать оператор +.

А>Как это лучше всего сделать?

канонический вид бинарного оператора + такой:
T operator+(const T& lhs, const T& rhs)
{
  T temp( lhs );
  temp += rhs;
  return temp;
}

заметь что он реализуется через operator +=
Хороший обзор возможных реализаций operator + даётся здесь

в принципе, при такой реализации можно понадеятся на NRVO (named return value optimization), которая поможет избежать создания временной переменной.

про RVO/NRVO можно почитать здесь

А>И вообще, напишите, что конкретно будет происходить, а также что должно быть выполнено до и после конструкции

А>a = b + c.
хорошо это описал Павел Кузнецов здесь
Автор: Павел Кузнецов
Дата: 25.10.03


если твои классы являются чем то типа массивов, то почитай про шаблоны выражений здесь
Re[2]: Большие объекты и операторы.
От: Аноним  
Дата: 20.10.04 17:15
Оценка:
Здравствуйте, korzhik, Вы писали:

Большое спасибо!
Re: Большие объекты и операторы.
От: e-Xecutor Россия  
Дата: 21.10.04 05:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Допустим, есть объект, для которого надо реализовать оператор +.

А>Как это лучше всего сделать?

А>- возвращать его по значению (но тогда ведь будет происходить копирование и копирующее присваивание)

А>- возвращать указатель на него (но тогда прийдётся записывать выражение для указателей, а не для объектов, типа
А>pA = pB + pC вместо a = b + c)
А>- возвращать ссылку на динамическую переменную (но как тогда пользователь догадается о необходимости уничтожения?)

А>И вообще, напишите, что конкретно будет происходить, а также что должно быть выполнено до и после конструкции

А>a = b + c.

А>Сразу ли результат будет положен в a, или сначала он будет вычислен, а потом будет применён оператор =?

А>В общем, распишите подробнее...

Есть еще такой подход.

Допустим есть класс Heavy с оч. тяжелой операцией копирования.
Хочется сделать operator+ подешевле, и что б работало без оглядки на возможности компилятора по оптимизации.

Можно сделать примерно так:

struct HeavyCollector;
class Heavy{
...
  Heavy& operator=(const HeavyCollector&);
...
};

struct HeavyCollector{
  HeavyCollector():count(0){}
  void Add(const Heavy& a)
  {
    coll[count++]=&a;
  } 
  HeavyCollector& operator+(const Heavy& a)
  {
    Add(a);
    return *this;
  }
  const Heavy* coll[REASONABLE_AMOUNT];
  int count;  
};

HeavyCollector operator+(const Heavy& a,const Heavy& b)
{
  HeavyCollector hc;
  hc.Add(a);
  hc.Add(b);
  return hc;
}

Heavy& Heavy::operator=(const HeavyCollector& hc)
{
  if(hc.count==0)return *this;
  *this=hc[0];
  for(int i=1;i<hc.count;i++)(*this)+=hc.coll[i];
}



Это набросок на коленке
Если суммируемое кол-во не влезло на коллектор,
остаток можно на хипе разместить.

Можно сделать безхиповый и безмассивный вариант —
со списком из темпоралов созданных на стэке
Но на неподготовленных людей он действует шокирующе
Re[7]: Большие объекты и операторы.
От: LaptevVV Россия  
Дата: 21.10.04 05:58
Оценка: +1
Здравствуйте, Аноним, Вы писали:

LVV>>>>>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.

А>>>>А как тогда реализуются операторы для больших объектов, возвращающие ссылки?
LVV>>>1. функция может вернуть ссылку, если она ее получила как параметр
LVV>>>2. можно вернуть ссылку на статическую переменную
LVV>>>3. можно вернуть ссылку на динамическую переменную — только пример попроси привести действующих програмистов — у меня под рукой нет, а они на практивке это делают.
А>>В конкретном примере нужно вернуть ссылку на некоторый новый объект.
А>>1 — не подходит,
А>>3 — тогда вряд ли будет выглядеть красивым delete &с где-то в программе.
А>>Остаётся второе.
А>>А вообще, в таких случаях это хорошо?

А>Мне кажется, что нехорошо... ведь в памяти может повиснуть в результате куча статических переменных.

Еще можно почитать про "ленинвые вычисления" или отложенное присваивание — у Мейерса, например в его книжках-советах. Там тоже как раз на больших объектах это объясняется — на матрицах.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[7]: Большие объекты и операторы.
От: ssm Россия  
Дата: 21.10.04 07:19
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Мне кажется, что нехорошо... ведь в памяти может повиснуть в результате куча статических переменных.


ну почему же куча? всего один на класс
Re[6]: Большие объекты и операторы.
От: ssm Россия  
Дата: 21.10.04 07:21
Оценка:
Здравствуйте, Аноним, Вы писали:


А>А вообще, в таких случаях это хорошо?


это применимо при работе с одним потоком, в противном случае прийдется синхронизировать работу данного метода, что будет ИМХО тяжелее чем возврат временного объекта по значению
Re[2]: Большие объекты и операторы.
От: korzhik Россия  
Дата: 23.10.04 18:04
Оценка:
Здравствуйте, korzhik, Вы писали:

K>канонический вид бинарного оператора + такой:

K>
K>T operator+(const T& lhs, const T& rhs)
K>{
K>  T temp( lhs );
K>  temp += rhs;
K>  return temp;
K>}
K>


правильней так:
const T operator+(const T& lhs, const T& rhs)
{
  // . . .
}

чтобы предотвратить присаивания типа: a + b = c;
Re[3]: Большие объекты и операторы.
От: Aera Беларусь  
Дата: 25.10.04 03:59
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, korzhik, Вы писали:


K>>канонический вид бинарного оператора + такой:

K>>
K>>T operator+(const T& lhs, const T& rhs)
K>>{
K>>  T temp( lhs );
K>>  temp += rhs;
K>>  return temp;
K>>}
K>>


K>правильней так:

K>
K>const T operator+(const T& lhs, const T& rhs)
K>{
K>  // . . .
K>}
K>

K>чтобы предотвратить присаивания типа: a + b = c;

Забавно, а я ошибочно полагал что все равно результатом будет rvalue
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
--
RedApe
Re[4]: Большие объекты и операторы.
От: elcste  
Дата: 25.10.04 04:39
Оценка:
Здравствуйте, Aera, Вы писали:

K>>правильней так:

K>>const T operator+(const T& lhs, const T& rhs)
K>>{
K>>  // . . .
K>>}

K>>чтобы предотвратить присаивания типа: a + b = c;

A>Забавно, а я ошибочно полагал что все равно результатом будет rvalue


Результатом-то будет rvalue, но у rvalues класс-типов никто не запрещает вызывать operator=.
Re[8]: Большие объекты и операторы.
От: Аноним  
Дата: 25.10.04 13:33
Оценка: +1
Здравствуйте, ssm, Вы писали:

ssm>Здравствуйте, Аноним, Вы писали:



А>>Мне кажется, что нехорошо... ведь в памяти может повиснуть в результате куча статических переменных.


ssm>ну почему же куча? всего один на класс


Со всеми вытекающими
например для такого кода


class A {
//...
}

const A& operator+(const A& left, const A& right)
{
static A result;
//...
return A;
}

// где-то в коде
A a, b, c, d;
//...
A result = (a + b) * (c + d);


Результату будет не хорошо.

Итого ссылка на статическую переменную не годится. Второй вариант от безысходности — статический массив — душим на корню без рассуждений.
Итого остается — возврат по значению. Или, если это совсем не катит по соображениям эффективности, то "отложенное присваивание"
Re[3]: Большие объекты и операторы.
От: Glоbus Украина  
Дата: 25.10.04 14:59
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Вообще-то — грубая ошибка для любого конкретного типа — возвращается ссылка на локальный объект. Последствия — непредсказуемы. Но с шаблонами у меня опыт небольшой, поэтому не могу определенно сказать, может сущетсуют ситуации. когда такая запись прокатит. Тебе гури наши точней скажут. Вс-таки, ИМХО, это крамола.


Дык...шаблоны/не шаблоны — ересь однозначно — возвращаем-то ведь действительно ссылку на локальный объект...
Удачи тебе, браток!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.