Member 3733166 Ответов: 2

Это ошибка компилятора или моя ошибка?


Выполните следующую программу дважды. Один раз с данным деструктором и один раз с "std::fesetround(value);", удаленным из деструктора. Почему я получаю разные результаты? Разве деструктор не должен вызываться после функции "add"?

#include <iostream>
#include <string>
#include <cfenv>

struct raii_feround {
  raii_feround() : value(std::fegetround()) {	 }
 ~raii_feround() { std::fesetround(value); }
  inline void round_up  () const noexcept { std::fesetround(FE_UPWARD  ); }
  inline void round_down() const noexcept { std::fesetround(FE_DOWNWARD); } 
  template<typename T>
  T add(T fst, T snd) const noexcept { return fst + snd; }
private: 
  int value; };

float a = 1.1;
float b = 1.2;
float c = 0;
float d = 0;
    
int main() {   
    {
        raii_feround raii;
        raii.round_up();
        c = raii.add(a, b);
    }
    {
        raii_feround raii;
        raii.round_down();
        d = raii.add(a, b);
    }
    std::cout << c << "\n"; // Output is: 2.3
    std::cout << d << "\n"; // Output is: 2.3 or 2.29999
}


Что я уже пробовал:

Я запустил обе версии на Оболочка C++

2 Ответов

Рейтинг:
2

Jochen Arndt

Деструктор вызывается, когда объект выходит за пределы области видимости. То есть после того, как add() наберите свой код.

Но режим округления влияет также на преобразование строк. Таким образом, разница в выходных данных не создается add() операции но путем распечатки результатов:
- Со сбросом режима cout использует начальный режим FE_TONEAREST
- Без сброса режима cout использует FE_DOWNWARD


Рейтинг:
0

CPallini

Это cout артефакт. Попробуйте, например

std::cout << std::setprecision(10) << c << "\n"; 
std::cout << std::setprecision(10) << d << "\n";