重新加载未定义的行为和序列点

重新加载未定义的行为和序列点

将此主题视为以下主题的续篇:

让我们重新审视这个有趣复杂的表达(斜体短语取自上述主题* smile *):

i += ++i;

我们说这会调用undefined-behavior。我假定说这个的时候,我们隐含假设i是内置的类型之一。

如果什么类型i是用户定义类型?比如它的类型是Index在本文后面定义的(见下文)。它还会调用未定义的行为吗?

如果是,为什么?它不等同于写作i.operator+=(i.operator++());甚至语法上更简单i.add(i.inc());吗?或者,他们是否也调用未定义的行为?

如果不是,为什么不呢?毕竟,对象在连续的序列点之间i被修改两次。请回想一下经验法则:表达式只能在连续的“序列点”之间修改一个对象的值。如果 i += ++i是表达式,那么它必须调用未定义的行为。如果是,那么它的等价物i.operator+=(i.operator++());也 i.add(i.inc());必须调用undefined-behavior似乎是不真实的!(据我所知)

或者,i += ++i不是一个开头的表达?如果是这样,那么它是什么以及表达式的定义是什么?

如果它是一个表达式,同时它的行为也是明确定义的,那么它意味着与表达式相关联的序列点的数量在某种程度上取决于表达式中涉及的操作数的类型。我是否正确(甚至部分)?


顺便问一下,这个表达怎么样?

//Consider two cases://1. If a is an array of a built-in type//2. If a is user-defined type which overloads the subscript operator!a[++i] = i; //Taken from the previous topic. But here type of `i` is Index.

你必须在你的回答中考虑这一点(如果你肯定知道它的行为)。:-)


++++++i;

在C ++ 03中定义明确?毕竟,就是这个,

((i.operator++()).operator++()).operator++();

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;
        }};


叮当猫咪
浏览 306回答 3
3回答

喵喵时光机

它看起来像代码i.operator+=(i.operator ++());关于序列点,完美地工作。C ++ ISO标准的1.9.17部分对序列点和功能评估进行了说明:在调用函数时(无论函数是否为内联函数),在评估函数体中任何表达式或语句之前发生的所有函数参数(如果有)之后,都会有一个序列点。在复制返回值之后和执行函数外部的任何表达式之前,还有一个序列点。例如,这将指示i.operator ++()作为参数operator +=在其评估之后具有序列点。简而言之,因为重载运算符是函数,所以适用正常的排序规则。很棒的问题,顺便说一下!我真的很喜欢你如何强迫我理解我已经认为我所知道的语言的所有细微差别(并且认为我认为我知道)。:-)

湖上湖

正如其他人所说,您的i += ++i示例使用用户定义的类型,因为您正在调用函数,而函数包含序列点。另一方面,a[++i] = i假设这a是您的基本数组类型,甚至是用户定义的数组类型,那就不那么幸运了。你在这里遇到的问题是我们不知道i首先评估表达式包含哪个部分。它可以被++i评估,传递给operator[](或原始版本)以便在那里检索对象,然后i传递给它的值(在i递增之后)。另一方面,可能首先评估后一侧,存储以供稍后分配,然后++i评估该部分。
打开App,查看更多内容
随时随地看视频慕课网APP