在上一部分中,“未定义的行为和序列点”我们讨论了与相关的潜在未定义行为表达式:
i += ++i;
当 i 是内置类型时,此表达式会调用未定义的行为,因为对象 i 在连续序列点之间被修改两次。
但是,如果i是用户自定义类型,比如定义的Index类下面:
class Index { int state; public: Index(int s) : state(s) {} Index& operator++() { state++; return *this; } Index& operator+=(const Index & index) { state+= index.state; return *this; } operator int() { return state; } Index & add(const Index & index) { state += index.state; return *this; } Index & inc() { state++; return *this; } };
表达式 i = i 是否仍然会调用未定义的行为?
令人惊讶的是,不会。具有用户定义类型 i 的表达式 i = i 不会调用未定义的行为,因为重载运算符被视为 C 中的函数。根据 C ISO 标准第 1.9.17 节:
调用函数时(无论函数是否内联),在所有函数参数求值之后都有一个序列点...
因此,对运算符和运算符 = 函数的调用会引入序列点,从而防止未定义的行为。
当 a 是带有重载下标运算符的用户定义类型时,表达式 a[ i] = i 也是明确定义的,因为在评估 i 表达式后,它被视为带有序列点的函数调用.
在 C 03 中,表达式 i 是明确定义的,因为它实际上是等价的to:
((i.operator++()).operator++()).operator++();
每个函数调用都会引入一个序列点,使表达式定义良好。
以上是C 中 `i = i` 总是未定义行为吗?的详细内容。更多信息请关注PHP中文网其他相关文章!