【问题标题】:cout variable and function that change variable by referencecout 变量和通过引用更改变量的函数
【发布时间】:2017-12-10 22:14:00
【问题描述】:

假设我们有下一个代码:

#include<iostream>

using namespace std;

int change(int &temp){
    temp += 2;
    return 10;
}

int main(){
    int nmb = 2;

    cout << change(nmb) << " " << nmb << endl;
}

我认为它应该像 cout 打印出 nmb 的新值一样工作,但它会打印旧版本的 nmb。

我得到的不是想要的结果 10 4,而是结果 10 2。 为什么 cout 会打印出 nmb 的旧值,因为 cout 先打印出变化,然后才打印出 nmb?

我是在g++下编译的,使用标准的c++11。

【问题讨论】:

  • cout &lt;&lt; change(nmb) &lt;&lt; " "; cout &lt;&lt; nmb &lt;&lt; endl; 你得到你的结果

标签: c++


【解决方案1】:

不,评估的顺序是实现定义的。

在 C++17 之前,评估的顺序是未指定的。 (请看 cmets 和 M.M 的回答。)

http://en.cppreference.com/w/cpp/language/eval_order

【讨论】:

  • 所以我不能像 cout
  • 如果 func 修改 nmb,规范不会说明会发生什么,不同的编译器可以生成以任一顺序计算表达式的代码。
  • 在该示例中,这是未定义的行为,因为i++ 修改了i,但与i 的其他读取相比没有排序
  • OP 的例子是函数调用,i++ 不是函数调用。函数的主体相对于调用上下文的顺序是不确定的(不像i++ 那样无序)。
  • 您可以将其编辑为“未指定”而不是“已定义实现”(并且可能提到您在 C++17 之前谈论,它刚刚发布)
【解决方案2】:

自 C++17 起,operator&lt;&lt; 具有左右排序(即左操作数在右操作数之前排序)。因此,如果您使用符合最新标准的编译器,您应该会看到10 4。 (参考:N4659 [over.match.oper]/2, [expr.shift]/4)

在 C++17 之前它是未指定的。

【讨论】:

    猜你喜欢
    • 2019-10-03
    • 2023-01-30
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    相关资源
    最近更新 更多