2

下面的代码片段来自 Herb Sutter 的博客

g++ 输出10。MSVC 也可以输出10。不同编译器的输出可能不同。

我不明白变量i是如何增加的。谁能解释一下输出是怎么来的10,输出10真的正确吗?

#include <iostream>
#include <vector>
#include <string>

int main()
{    
    std::vector<int> v = { 0, 0 };
    int i = 0;
    v[i++] = i++;
    std::cout << v[0] << v[1] << std::endl;
}
4

2 回答 2

1

已编辑

我们将不讨论未定义的行为,只关注您的程序如何到达指定的输出。

首先,让我们陈述一个事实:

  • i++ 将增加 i 的值,但返回 i 在增加之前持有的原始值。

++i 和 i++ 有什么区别?.

现在,线

v[i++] = i++;

在您的情况下,按“LHS”->“RHS”-> 分配的顺序评估:

  • LHS,v[i++]:i 递增到 1,i++ 返回 0 到 v[i++]。
  • RHS,i++:i 现在的值为 1,但递增到 2,但是 RHS 的 i++ 返回 1。
  • 赋值:从上面看,赋值结果为:v[0] = 1(之后 i 的值为 2)。

因此,打印 v[0] 和 v[1] 将分别评估为 1(更新值)和 0(初始化)。

于 2015-12-07T10:33:18.263 回答
-1

这是执行顺序的问题,由于 c++11,它是未定义的:

5.17 赋值和复合赋值运算符

赋值运算符 (=) 和复合赋值运算符都从右到左分组。所有这些都需要一个可修改的左值作为它们的左操作数,并返回一个指向左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。

简单地说,左参数的修改是在值计算之后排序的,而不是计算的副作用,双方和返回对对象的引用之前。

所以要采取的行动是

A. 评估左侧(表达式 i++ = 0 的返回值)

B. 返回对对象的引用(返回对表达式 v[i++] 的对象的引用)

C. 计算左侧的副作用,即 i-> 1

D. 计算右侧的副作用,即 i-> 2

正如您从上面的规则中看到的那样,不清楚顺序是 ABCD 还是应该是 ACBD ,因为没有定义副作用计算的顺序,它应该首先发生在左侧还是首先发生在右边。

于 2015-12-07T10:26:47.343 回答