很抱歉再次打开这个话题,但是考虑这个话题本身已经开始给我一个未定义的行为。想要进入定义明确的行为区域。
给定
int i = 0;
int v[10];
i = ++i; //Expr1
i = i++; //Expr2
++ ++i; //Expr3
i = v[i++]; //Expr4
我认为上述表达式(按此顺序)为
operator=(i, operator++(i)) ; //Expr1 equivalent
operator=(i, operator++(i, 0)) ; //Expr2 equivalent
operator++(operator++(i)) ; //Expr3 equivalent
operator=(i, operator[](operator++(i, 0)); //Expr4 equivalent
现在谈到这里的行为是来自C++ 0x的重要引述。
$1.9/12-“表达式(或子表达式)的评估通常包括值计算(包括确定对象的身份以进行左值评估和获取先前分配给对象以进行右值评估的值)和副作用的启动。”
$1.9/15-“如果标量对象的副作用相对于同一标量对象的另一个副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。”
[注意:与不同参数表达式相关的值计算和副作用是无序的。——尾注]
$3.9/9-“算术类型 (3.9.1)、枚举类型、指针类型、指向成员类型的指针 (3.9.2)、std::nullptr_t 和这些类型的 cv 限定版本 (3.9.3) 统称为标量类型。”
在 Expr1 中,表达式
i
(第一个参数)的评估相对于表达式的评估operator++(i)
(具有副作用)是无序的。因此 Expr1 具有未定义的行为。
在 Expr2 中,表达式
i
(第一个参数)的评估相对于表达式operator++(i, 0)
(具有副作用)的评估是无序的。因此 Expr2 具有未定义的行为。
在 Expr3 中,
operator++(i)
需要在调用外部参数之前完成对单独参数的评估operator++
。因此,Expr3 具有明确定义的行为。
在 Expr4 中,表达式
i
(第一个参数)的计算相对于operator[](operator++(i, 0)
(有副作用)的计算是无序的。因此 Expr4 具有未定义的行为。
这种理解正确吗?
PS OP中分析表达式的方法不正确。这是因为,正如@Potatoswatter 所指出的那样 - “第 13.6 条不适用。请参阅 13.6/1 中的免责声明,“这些候选函数参与 13.3.1.2 中所述的运算符重载解决过程,并且不用于其他目的。 “它们只是虚拟声明;不存在与内置运算符相关的函数调用语义。”