代码之家  ›  专栏  ›  技术社区  ›  Dan

流中多次设置值

c++
  •  3
  • Dan  · 技术社区  · 6 年前

    是否可以在单个流中多次设置值,如 std::cout ?

    例如,下面的代码生成以下输出。


    0个
    1个

    1个

    这让我很惊讶,因为我正期待着结果


    0个

    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 回复  |  直到 6 年前
        1
  •  3
  •   M.M    6 年前

    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++给出了虚假的警告,甚至在某些情况下在这方面的错误行为。

        2
  •  2
  •   Geezer    6 年前

    您没有指定编译器/标志,所以我鼓励您确保您正在构建C++ 17(CLAN/G++标志)。 -std=c++17 ). 这将修复您的结果,但仍可能导致编译警告。下面是如何和为什么。更新:不像clang和gcc, msvc似乎完全符合这一点

    说明: 事实上,这个意外的结果与流操作没有特别的关系。这和 未排序的计算 [intro.execution] :

    除非另有说明 ,计算单个运算符的操作数 未排序 . 如果内存位置上的副作用相对于同一内存位置上的任何一个副作用是未排序的 或者使用同一内存位置中任何对象的值进行值计算,[…] 行为是不确定的

    ...

    i = i++ + i; // the behavior is undefined

    但你看, << 操作员( )正在被特别注意 [expr.call] :

    如果使用运算符符号调用运算符函数,则参数 按照内置操作员的指定顺序进行评估;

    再加上这个 [expr.shift] :

    表达式E2。

    clang 6.0.1给出了这个信息警告 根据规范的摘录 不符合标准(!)

    警告:对“x”的多个未排序修改[-Wunsequenced] std::cout << (x = true) << std::endl

    你可以看到它 here live .

    this enlightening SO link 它指的是关于clang和GCC的错误报告。

        3
  •  0
  •   Matthias247    6 年前

    std::cout << (x = true) << std::endl
        << (x = false) << std::endl;
    

    在打印任何内容之前,将以未定义的顺序计算这两个子表达式。所有人都给 x ,但最后一个赋值“获胜”,并将最终值(在本例中为true)写入 . 那么 打印三次。