流中多次设置值

时间:2018-08-19 18:58:43

标签: c++

是否可以在单个流(例如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;
}

3 个答案:

答案 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被打印三遍。