很抱歉再次打开了这个话题,但是思考这个主题本身已经给了我一个未定义的行为。想要进入定义良好的行为区域。
给定的
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-“对表达式(或子表达式)的评估一般包括值计算(包括确定用于lvalue计算的对象的标识,以及获取以前分配给一个对象用于rvalue评估的值)和产生副作用。”
$1.9/15-“如果对标量对象的副作用相对于对同一个标量对象或的另一个副作用(使用同一个标量对象的值计算)没有排序,则行为是未定义的。”
注意:与不同参数表达式相关联的值计算和副作用是不按顺序排列的。-end注记
$3.9/9-“算术类型(3.9.1)、枚举类型、指针类型、指向成员类型的指针(3.9.2)、std::nullptr_t和cv限定的这些类型的版本(3.9.3)统称为标量类型。
i (第一个参数)的评估,它与对支出operator++(i) (有副作用)的评估不相关。因此,behavior.
i (第一个参数)的计算,它与对支出operator++(i, 0) (有副作用)的评估不相关。因此,behavior.
operator++之前,必须完成对唯一参数operator++(i)的计算。因此,behavior.
i (第一个参数)的计算与operator[](operator++(i, 0)的计算无关(这有副作用)。因此,behavior.具有未定义的Expr4
这种理解是正确的吗?
分析运算式的方法是不正确的。这是因为,正如@Potatoswatter所指出的--“第13.6条不适用。参见13.6/1中的免责声明,”这些候选函数参与了13.3.1.2中描述的操作符过载解析过程,没有其他用途。“它们只是虚拟声明;内置运算符不存在函数调用语义。”
发布于 2011-11-01 14:55:31
在思考那些像提到的表达式时,我发现想象一台内存有联锁的机器是很有用的,这样作为读-修改-写序列的一部分读取内存位置将导致任何尝试读或写,除了序列的结束写入之外,都会被延迟,直到序列完成。这样的机器几乎不是一个荒谬的概念;事实上,这样的设计可以简化许多多线程代码场景。另一方面,如果'x‘和'y’是对同一个变量的引用,像"x=y++;“这样的表达式可能会在这样的机器上失败,而编译器生成的代码会执行类似于读和锁reg1=y;reg2=reg1+1;read x=reg1;书面-和-unlock y=reg2之类的操作。这将是处理器上非常合理的代码序列,其中写入新计算的值将导致管道延迟,但是如果y被别名为相同的变量,写到x将锁定处理器。
https://stackoverflow.com/questions/3852768
复制相似问题