Форум программистов, компьютерный форум CyberForum.ru

Ленивые вычисления - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.78
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5547 / 2561 / 233
Регистрация: 01.11.2011
Сообщений: 6,330
Завершенные тесты: 1
03.07.2013, 10:25     Ленивые вычисления #1
____Много есть информации под boost, так же не отстает шарп и опережает всех хаскель. В плюсах только со стандарта C++0x. Даже попалась цельная Qt-шная библиотека для этого дела. Вообще концепция ленивых вычислений зародилась для функциональных языков. Но это все придумано, если возвращаться к C++, для удобства оперирования функторами и еще каких-то таинств. Но по сути же простые "ленивые вычисления" доступны во многих языках, компиляторы которых действуют по некоему принципу call by value. То есть когда значение получено, дальше его обсчитывать смысла нет. Если первый операнд операции && ложен, то вычислять следующие не нужно.
____Общий смысл "ленивых вычислений" в том, что экономится время на проведении вычислений, результаты которых заведомо не будут использованы в дальнейшем программой. Соответственно, за счет снижения объемов вычислений повышается и производительность программы, а за счет отсутствия необходимости хранить в памяти результаты вычислений снижаются и требования программы к памяти. Помимо этого, ленивые вычисления избавляют программиста от необходимости следить за тем, какие именно вычисления будут в дальнейшем востребованы программой, а какие, напротив, окажутся совершенно бесполезными. Последнее не всегда хорошо, учитывая опять же гибкость плюсов, в которых компилятор не даст, вопреки обычному подходу, поступать как заблагорассудится программисту. Но на то в принципе и расчет.

Принцип "ленивого вычисления" проще всего рассмотреть на следующем примере:
C++
1
if (A && B && C && D) {...}
C++
1
2
3
4
5
6
7
8
9
if (A) {
  if (B) {
    if (C) {
      if (D) {
        ...
      }
    }
  }
}
В первом случае не понятно, что, если A ложно, то и остальные вычисления происходить не будут. Во-втором же наглядно видно, что, при ложном A, тело первого оператора условия не будет выполнено.
Оба приведенных кода делают одно и то же. Отличие лишь в компромиссе между читабельностью кода и его объемом.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryS
Модератор
6374 / 4840 / 441
Регистрация: 14.02.2011
Сообщений: 16,040
03.07.2013, 10:31     Ленивые вычисления #2
можно добавить еще такую конструкцию
C++
1
2
3
4
if(A|| B ||C)
{
......
}
равно

C++
1
2
3
4
5
6
if(!A)
 if(!B)
  if(!C)
   {
    .......
    }
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 10:37     Ленивые вычисления #3
Цитата Сообщение от SatanaXIII Посмотреть сообщение
В плюсах только со стандарта C++0x.
Не понял, Вы хотите сказать, что "ленивость" появилась в плюсах только начиная с C++0x?

Добавлено через 2 минуты
Цитата Сообщение от SatanaXIII Посмотреть сообщение
В первом случае не понятно, что, если A ложно, то и остальные вычисления происходить не будут.
Смотря чем являются эти A,B,C,D
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 10:41     Ленивые вычисления #4
SatanaXIII, и в чем же вопрос?
ValeryS
Модератор
6374 / 4840 / 441
Регистрация: 14.02.2011
Сообщений: 16,040
03.07.2013, 10:42     Ленивые вычисления #5
Цитата Сообщение от ValeryS Посмотреть сообщение
можно добавить еще такую конструкцию
соврал ведь я думал о порядке вычисления а про условие не подумал
вот так должно выглядеть
C++
1
2
3
4
if(A || B || C)
{
// что то делаем 
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(A)
 {
  // что то делаем 
 }
 else
{
   if(B)
  {
   // что то делаем 
  }
  else
   {
    if(C)
    {
     // что то делаем 
     } 
   }
 }
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 10:45     Ленивые вычисления #6
Цитата Сообщение от Croessmah Посмотреть сообщение
Смотря чем являются эти A,B,C,D
чем бы не являлись §5.14/1:
The && operator groups left-to-right. The operands are both contextually converted to type bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5547 / 2561 / 233
Регистрация: 01.11.2011
Сообщений: 6,330
Завершенные тесты: 1
03.07.2013, 10:49  [ТС]     Ленивые вычисления #7
Цитата Сообщение от Croessmah Посмотреть сообщение
Не понял, Вы хотите сказать, что "ленивость" появилась в плюсах только начиная с C++0x?
Не совсем:
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Но это все придумано, если возвращаться к C++, для удобства оперирования функторами и еще каких-то таинств
Честно сказать, я тут не до конца разобрался.

Цитата Сообщение от Croessmah Посмотреть сообщение
Смотря чем являются эти A,B,C,D
Положим функциями:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool A(){cout << " A "; return true;}
bool B(){cout << " B "; return false;}
bool C(){cout << " C "; return false;}
bool D(){cout << " D "; return false;}
 
 
int main(int argc, char* argv[])
{
 
if (A() && B() && C() && D())
  {cout << "done";}
 
 
 
if (A())
  {
  if (B())
  {
    if (C())
    {
      if (D())
      {
        cout << "done";
      }
    }
  }
}
Добавлено через 46 секунд
Цитата Сообщение от Tulosba Посмотреть сообщение
и в чем же вопрос?
Да ни в чем. ) Хочется обсудить. Все верно описно?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 10:54     Ленивые вычисления #8
Цитата Сообщение от Tulosba Посмотреть сообщение
чем бы не являлись §5.14/1:
Если в классе перегружены логические операторы, то их ленивость теряется, ибо это уже не совсем операторы
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 11:41     Ленивые вычисления #9
Цитата Сообщение от Croessmah Посмотреть сообщение
Если в классе перегружены логические операторы, то их ленивость теряется, ибо это уже не совсем операторы
show me example

Добавлено через 24 минуты
Собственно, сам родил:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
 
class A
{
public:
    A( int a ) : a(a) { }
    A operator&&( const A& a )
    {
        std::cout << "operator &&" << std::endl;
        return *this;
    } 
    
    operator bool()
    {
        std::cout << "operator bool : " << a << std::endl;
        return false;
    }
    
    A& operator()() 
    { 
        std::cout << "operator () : " << a << std::endl;
        return *this; 
    }
private:
    const int a;
};
 
int main() {
    
    A a1(1), a2(2), a3(3);
    
    if( a1() && a2() && a3() )
    {
        
    }
    
    return 0;
}
https://ideone.com/YdbmM6

Если убрать operator&& из класса, то operator() вызовется только для a1.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 11:53     Ленивые вычисления #10
Цитата Сообщение от Tulosba Посмотреть сообщение
The && operator groups left-to-right
Наверное, одним из самых важных аргументов будет то, что эти операторы являются
Цитата Сообщение от Tulosba Посмотреть сообщение
groups left-to-right
тогда как operator||уже таким не будет.
Для примера, вот просто, банально и бездарно:
http://ideone.com/R1p7Oo
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 12:02     Ленивые вычисления #11
Цитата Сообщение от Croessmah Посмотреть сообщение
Для примера, вот просто, банально и бездарно:
http://ideone.com/R1p7Oo
Не очень понял, что показывает этот пример. Тут ведь если убрать из класса operator||, то даже не скомпилируется.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 12:04     Ленивые вычисления #12
Цитата Сообщение от Tulosba Посмотреть сообщение
Не очень понял, что показывает этот пример
Выражение в условии:
C++
1
(a || *a)
а выполнение:
operator*
operator||(A,A)
то есть уже имеем не left-to-right порядок, который можно предположить при чтении кода
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 12:22     Ленивые вычисления #13
Цитата Сообщение от Croessmah Посмотреть сообщение
то есть уже имеем не left-to-right порядок,
Это уже получается порядок вычисления аргументов функции, а он, как известно, в стандарте не регламентирован.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 12:25     Ленивые вычисления #14
Цитата Сообщение от Tulosba Посмотреть сообщение
Это уже получается порядок вычисления аргументов функции, а он, как известно, в стандарте не регламентирован.
вообще, наверное, лучше перегрузить void*, вместо всех этих логических операторов, в т.ч. преобразование к bool
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 12:32     Ленивые вычисления #15
Цитата Сообщение от Croessmah Посмотреть сообщение
вообще, наверное, лучше перегрузить void*, вместо всех этих логических операторов, в т.ч. преобразование к bool
какой профит?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 13:05     Ленивые вычисления #16
Tulosba, из-за перегрузки преобразования bool иногда могут возникнуть неприятные касты
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 13:59     Ленивые вычисления #17
Croessmah, а что если http://en.wikibooks.org/wiki/More_C++_Idioms/Safe_bool ?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 18:03     Ленивые вычисления #18
Цитата Сообщение от Tulosba Посмотреть сообщение
а зачем? Лишнийе геморрой проблемы себе на голову
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.07.2013, 18:27     Ленивые вычисления #19
Цитата Сообщение от Croessmah Посмотреть сообщение
а зачем?
я про C++11 версию в частности (explicit bool)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.07.2013, 18:31     Ленивые вычисления
Еще ссылки по теме:

C++ Параллельные вычисления
Вычисления C++
C++ Написать процедуру для вычисления коэффициентов и функцию для вычисления значения многочлена

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
03.07.2013, 18:31     Ленивые вычисления #20
Цитата Сообщение от Tulosba Посмотреть сообщение
я про C++11 версию в частности (explicit bool)
Не заметил Чтобы не говорили, но в 11 стандарте появилось много плюшек. Ждем рефлексию
Yandex
Объявления
03.07.2013, 18:31     Ленивые вычисления
Ответ Создать тему

Метки
ленивые операторы вычисления
Опции темы

Текущее время: 04:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru