是否可以在单个流(例如std::cout
)中多次设置一个值?
例如,下面的代码将产生以下输出。
1
0
1
1
1
这让我感到惊讶,因为我期待着输出
1
0
1
0
0
据我所知,当它们全部串联在一起时,(x = false)
被忽略,它只打印x
。
#include "stdafx.h"
#include <iostream>
int main()
{
bool x;
std::cout << (x = true) << std::endl;
std::cout << (x = false) << std::endl;
std::cout << (x = true) << std::endl
<< (x = false) << std::endl;
std::cout << x << std::endl;
return 0;
}
答案 0 :(得分:3)
Since C++17,该代码的正确输出是您期望的1 0 1 0 0
。
在C ++ 17之前,该行为是未定义的。 C ++ 17标准引入了<<
操作数的从左到右排序。
如果编译器在C ++ 17模式下没有提供预期的输出(-std=c++17
),则它是编译器错误。 It has been previously noted上的similar questions表示最新版本的g ++和clang ++给出了虚假警告,甚至在某些情况下,该区域的行为不正确。
答案 1 :(得分:2)
简短答案:
您未指定编译器/标志,因此建议您确保要为C ++ 17(clang / g ++标志-std=c++17
)构建。这应该可以修复您的结果,尽管仍然可能会导致编译警告。下面是如何和为什么。更新:与clang和gcc不同, msvc似乎完全符合这一要求 –给出了预期的结果,没有警告。
说明: 确实,这种意外结果确实与流操作无关。它与操作数的 无序评估 有关。在[intro.execution]中查看此处:
除非另有说明,否则对各个运算符的操作数进行评估 和单个表达式的子表达式的未排序。 …………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………… 如果相对于同一存储位置上的另一种副作用,没有对某个存储位置上的副作用进行排序,或者使用同一存储位置中任何对象的值进行的值计算,[...] < strong>行为未定义。
...
i = i++ + i; // the behavior is undefined
但是,请注意,<<
运算符( shift运算符)是专门要在当前规范中排序的(自C ++ 17起)在[expr.call]中看到此处:
如果使用运算符符号,参数调用了运算符功能 评估按内置运算符的指定顺序进行;
与此相结合的是[expr.shift]:
E1的值>> E2 ...表达式E1在 表达式E2。
对于您的摘录, clang 6.0.1发出此提示性警告,根据规范摘录的这些摘录与标准(!)不符:>
警告:对'x'的多个未排序修改[-未排序]
std::cout << (x = true) << std::endl
您可以here live看到它。
注意:感谢用户M.M带来了this enlightening SO link,该答案引用了有关clang和GCC的相应错误报告,此答案已被编辑以反映当前情况。
答案 2 :(得分:0)
误解来自此行:
Error in file(file, "rt") : cannot open the connection to 'https://raw.githubusercontent.com/fivethirtyeight/data/master/airline-safety/airline-safety.csv'
In addition: Warning message:
In file(file, "rt") :
URL 'https://raw.githubusercontent.com/fivethirtyeight/data/master/airline-safety/airline-safety.csv': status was 'Problem with the SSL CA cert (path? access rights?)'
在打印任何内容之前,将以不确定的顺序评估两个子表达式。全部分配给std::cout << (x = true) << std::endl
<< (x = false) << std::endl;
,但最后一个分配“获胜”,并将最终值(在这种情况下为true)写入x
。然后x
被打印三遍。