2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 05:18 


06/04/18

323
В одной книге написано, что в C++ используется "сокращенная" логика вычисления выражений. Это означает, что если после вычисления одной части выражения ясен конечный результат, то остальная часть выражения не вычисляется. В то же время метод сокращенного вычисления может послужить источником труднообнаруживаемых ошибок, если одно из невычисляемых выражений каким-то образом могло повлиять на состояние программы (например, путем вызова некоторой функции).

Ну я проверил. Есть два кода которые отличаются только инициализацией переменной test:
Используется синтаксис C++
#include <iostream>
using namespace std;

int f(){
    cout<<"Test";
    return 19;
}

int main() {
//    bool test = ( f()>=20 );
//    bool test = true || ( f()>=20 );
    return 0;
}
Если раскомментировать только первый комментарий, то программа выводит Test, а если только второй — программа ничего не выводит. Это особенность конкретной реализации или строгое требование стандарта ?

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 05:25 
Аватара пользователя


11/06/12
10390
стихия.вздох.мюсли
Не надо свинячить. Делать часть поста курсивом не значит что-то цитировать. В какой книге и на какой странице это написано?
Qlin в сообщении #1432625 писал(а):
Это особенность конкретной реализации
Укажите тогда свою конкретную реализацию.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 06:13 
Заслуженный участник


16/02/13
4194
Владивосток
Вообще-то, насколько мне известно, это стандарт. Не стандарт «логики вычисления выражений», а стандарт операций || и &&, только и всего.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 06:27 


06/04/18

323
Нашлось подходящее место в стандарте:
пункт 7.6.15 писал(а):
Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.

The result is a bool. If the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression.
Тогда вопрос сводится к следующему: может ли быть побочный эффект без вычисления значения подвыражения?
iifat в сообщении #1432628 писал(а):
Вообще-то, насколько мне известно, это стандарт. Не стандарт «логики вычисления выражений», а стандарт операций || и &&, только и всего.
Тоже важный момент. Авторы (конкретно Николас Солтер и Скотт Клепер) утверждают, что это относится к любым выражениям вообще. Я проверил. Не относится:
Используется синтаксис C++
#include <iostream>
using namespace std;

int f(){
    cout<<"Test";
    return 19;
}

int main() {
    int test = 0 * (0 % f());
    return 0;
}

Программа выводит слово, хотя значение выражения в целом можно предугадать без вычисления значений всех подвыражений.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 11:35 
Заслуженный участник


20/08/14
11760
Россия, Москва
Мне снова кажется что это относится к любым выражениям вообще лишь в смысле возможностей оптимизатора: увидит что нет побочных эффектов правой части выражения - может и исключит кусок кода. Но в общем случае определить отсутствие побочных эффектов достаточно сложно, а иногда и вовсе невозможно. Вывод в поток - натуральный побочный эффект и исключать вызов нельзя.
И лишь для логических операций (|| и &&) прямо оговорена возможность упразднить правую часть. Остальное отдано оптимизатору.

Какие-то странные Вы книги читаете, путают требования стандарта и возможности оптимизатора. Т.е. совет-то в цитате правильный, но лишь в обычных условиях, а не всегда.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 19:24 
Заслуженный участник
Аватара пользователя


16/07/14
9143
Цюрих
Qlin в сообщении #1432631 писал(а):
Тогда вопрос сводится к следующему: может ли быть побочный эффект без вычисления значения подвыражения?
В цитате, которую вы привели строчкой выше, написано, что не может.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 19:35 


10/04/12
705
Нет, просто стандарт гарантирует, что при вычислении оператора && первым будет вычислен первый операнд, и если его значение true, то будет вычислен второй операнд. Таким образом можно писать if (obj != NULL && obj->value > 0) std:cout << obj->value; не опасаясь того, что оптимизатор решит прочитать значение obj->value до проверки obj на NULL.
Аналогично с ||.
А вот в отношении умножения * стандарт говорит о том, что порядок вычисления операндов как оптимизатору удобнее, но они будут обязательно вычислены.
И т. д., для каждого оператора свои правила.

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 19:47 
Заслуженный участник
Аватара пользователя


30/01/06
72407
А говорит ли стандарт, что обязательно будет вычислен инициализатор переменной, которая потом нигде (включая побочные эффекты) не используется?

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение30.12.2019, 22:22 


06/04/18

323
mihaild в сообщении #1432746 писал(а):
В цитате, которую вы привели строчкой выше, написано, что не может.
В цитате, которую я привел ничего подобного не написано. И вообще там речь только о ||. Но в cppreference сказано, что evaluation of each expression includes: value computations, initiation of side effects.
Munin в сообщении #1432751 писал(а):
А говорит ли стандарт, что обязательно будет вычислен инициализатор переменной, которая потом нигде (включая побочные эффекты) не используется?
Отсюда: http://eel.is/c++draft/basic.stc
6.7.5.3 Automatic storage duration писал(а):
If a variable with automatic storage duration has initialization or a destructor with side effects, an implementation shall not destroy it before the end of its block nor eliminate it as an optimization, even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in [class.copy.elision].

 Профиль  
                  
 
 Re: Сокращенное вычисление выражений в C++
Сообщение31.12.2019, 00:03 
Заслуженный участник
Аватара пользователя


16/07/14
9143
Цюрих
Qlin в сообщении #1432776 писал(а):
В цитате, которую я привел ничего подобного не написано

Qlin в сообщении #1432631 писал(а):
the second operand is not evaluated if the first operand evaluates to true

Так что если первый аргумент истинен, то второй не вычисляется.
Про && написано в 7.6.14.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group