为什么cout.precision()会影响整个流?

iks*_*nov 2 c++ iostream c++-standard-library

我觉得我问的是一个非常基本的问题,但我无法在这里或谷歌找到答案.我记得我们在学校教过这个,但是它已经消失多年了.

为什么cout.precision()(std::ios_base::precision())在输出列表中间调用时会影响整个流?我知道std::setprecision()应该用来改变运行精度的规则,这cout.precision()将破坏输出的返回值.但是这个的机制是什么?是因为缓冲吗?手册陈述这些"做同样的事情",但凭经验我可以看出它并非完全正确.

MCVE:

const double test = 1.2345;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
cout << test << endl << cout.precision(3) <<  test << endl;

// Output:
// 1.234
// 21.234

// after the same init
cout.precision(2);
cout << test << endl << setprecision(3) <<  test << endl;

// Output
// 1.23
// 1.234
Run Code Online (Sandbox Code Playgroud)

这是"具体/未由标准定义的实施"吗?请随意将其标记为重复,因为我无法在SO上找到它.

Die*_*ühl 5

函数参数评估的顺序未指定.当你调用' std::cout.precision(n)的精度时,std::cout会对此调用进行评估.在你的表达

cout << test << endl << cout.precision(3) <<  test << endl;
Run Code Online (Sandbox Code Playgroud)

cout.precision(3)是,很显然,被称为其编译器完全允许做的第一件事.请记住,编译器认为上述语句等效于

std::cout.operator<<(test)
          .operator<<(std::endl)
          .operator<<(std::cout.preision(3))
          .operator<<(test)
          .operator<< (std::endl);
Run Code Online (Sandbox Code Playgroud)

实际上,似乎您的编译器函数参数从右到左进行计算.只有这样才能执行不同的移位运算符.结果,在输出完成之前精度会发生变化.

使用类似于std::setprecision(n)避免依赖订单子表达式的操纵器进行评估:创建临时创建的std::setprecision(n)是随时创建的.然后在调用适当的移位运算符时应用效果.由于必须以适当的顺序调用移位操作符,因此操纵器的使用发生在已知的位置.