3

为什么第一个表达式允许,而第二个不允许:

void test()
{
   int a;

   ++a = getSomeInt();
   a++ = getSomeInt();
}

我的意思是,为什么禁止第二个是左值?第二个有意义,第一个没有。在第一个中,我们增加了变量,在我们给这里一个新值之后,我们立即丢失了它。在第二个表达式中不是这种情况。在此之后分配一些值并增加变量是有意义的。

4

1 回答 1

7

后缀增量的结果是右值,表示纯右值,因此不可修改。这是根据后缀表达式部分增量和减量下的C++ 标准草案强调我的):5.2.6

后缀 ++ 表达式的值是其操作数的值。[注意:获得的值是原始值的副本-end note] [...]结果是prvalue。[...]

如果您考虑一下,这是有道理的,因为您需要返回a它的先前值必须是一个临时值。

为了完整起见,增量和减量部分中前缀增量的语言说(强调我的):5.3.2

前缀 ++ 的操作数通过加 1 来修改,或者如果它是 bool 则设置为 true(不推荐使用此用法)。操作数应为可修改的左值。操作数的类型应为算术类型或指向完全定义的对象类型的指针。结果是更新的操作数;它是一个左值[...]

更新

我意识到:

++a = getSomeInt();

C++03中调用未定义的行为,我们可以看到,通过查看旧标准草案中的相关部分将是表达式4节,它说:5

[...]在前一个和下一个序列点之间,一个标量对象的存储值最多只能通过表达式的评估修改一次。此外,只能访问先验值以确定要存储的值。对于完整表达式的子表达式的每个允许排序,都应满足本段的要求;否则行为未定义。

因此,由于您多次修改它是 undefined。据我所知,这在C++11中有很好的定义,在程序执行15段中说:a1.9

除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值是无序的。[...]如果标量对象的副作用相对于同一标量对象的另一个副作用或使用同一标量对象的值的值计算是无序的,则行为未定义。

我们可以在5.17 赋值和复合赋值运算符1段中看到:

[...] 在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。[...]

但无论如何,即使它是这样定义明确的表达式:

++a = getSomeInt();

难以阅读和维护,应该避免使用更简单的代码。

更新 2

不知道我是怎么错过这个的,但你没有a在这里初始化:

 int a;

所以它会有一个不确定的值,我们不知道它的初始值是什么,并且执行预增量a也将是未定义的行为。

于 2013-11-01T15:18:33.857 回答