2012-02-10 41 views
2

可能重复:
How do we explain the result of the expression (++x)+(++x)+(++x)?
Undefined Behavior and Sequence PointsC + C++ =未定义的行为?

我有问题,在不同方式的代码

U = C + C++; 

会运行非标准类型和我自己的类型。 我举一个例子http://ideone.com/4S1uA其中我有不同的int值和我的类Int值,它应该代表真正的Int工作方式。

是否有可能使我的类的行为方式与标准int的工作方式相同?此代码是否有未定义的行为?

为什么它是非玩家的行为? C++有一个操作优先级,所以c++应该先评估,因为它会改变a的值,所以为了增加第一个参数应该传递新值a并作为第二个旧值。它对Int类是这样工作的,但对于standart int不适用。

+5

是的,这是未定义的行为。我会让其他人创建一个答案,引用标准等。 – 2012-02-10 20:45:01

+1

请参阅http://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviour-that-ac-programmer -should-know-ab – Dervall 2012-02-10 20:46:22

+1

是的,它是UB,因为它是未定义的,否则将首先评估“C”或“C++”。 – 2012-02-10 20:46:56

回答

4

此代码未定义的行为?

是的。关于副作用,操作数的评估顺序是未定义的。

第6.5节(2)的标准的说:

如果一个标量对象上的副作用是相对于相同的标量对象上或者是不同的副作用或一个值计算未测序使用的值同一个标量为 的对象,其行为是未定义的。如果子表达式的子表达式存在多个允许的排序顺序,则如果在任何排序中出现这种不确定的方面效应,则行为是不确定的。

由于int是一个标量类型,并且由于此处的副作用是未定义的,因此行为未定义。

你应该写你这样的代码:

U = 2*C; 
C++; 
+0

我无法想象需要构建'c + C++'时的情况,但是我对这个代码应该如何工作有一些争论。但是C++有一个操作优先级,所以应该首先评估C++,因为它改变了a的值,所以为了增加,第一个参数应该是新值的改变,而第二个是旧值。但是这对于构建类型不起作用。 – Seagull 2012-02-10 20:53:23

+2

操作数评估的顺序未定义。 – 2012-02-10 20:56:01

+3

@海鸥:这不是运营商优先的问题。是的,++操作在+操作之前发生(由于优先级),但不会告诉您何时在该操作的左侧评估C的值。 – 2012-02-10 20:58:21

2

是的,这是不确定的行为。在语句中也不能访问变量两次,该语句也会修改它,因为未定义表达式“C”和表达式“C++”的求值顺序。

2

这里涉及的概念是sequence points之一。

在命令式编程的序列点定义了它保证了先前评估的所有副作用将被执行的计算机程序的执行任意点,无副作用:从维基百科的文章引用开头一句来自后续评估的效果尚未完成。

在C中,操作者+确实创建序列点。因此副作用的顺序没有定义。但是,在C++中,重载的operator +是一个函数调用,它确实创建了一个序列点。这会在副作用方面产生不同的行为。请注意,虽然未指定评估函数参数的顺序,但在函数进入之前所有副作用都已完成。因此,如果C + C++涉及过载的+运算符,则在执行+函数之前+的左边参数将应用于函数。这与int值的情况不同,其中在完成右侧的副作用之前可以评估或不评估左侧。

+0

'如果C + C++涉及一个重载的+运算符,那么在+函数执行之前,C++副作用将应用于+的左参数。否,'f(c,C++)'对于标量c也是UB。 – Cubbi 2012-02-10 21:14:25

+0

@Cubbi - 我没有说这种行为是必然定义的。我说在'+'执行之前'++'的副作用已经完成了(不像内建的'+'运算符,它不会创建一个序列点)。对于标量,显然参数评估(UB)的顺序决定了传递给函数的值。对于对象来说,问题的关键是''看作左边的参数,保证包含'++'的效果。 – 2012-02-12 19:00:34