C++ 它和它的行为

C++ 它和它的行为,c++,iterator,post-increment,pre-increment,C++,Iterator,Post Increment,Pre Increment,在函数调用的上下文中,it++和++it的行为的解释是什么?更具体地说,对于函数iter\u swap?下面代码中的调用2和调用4似乎在交换元素,而调用3和调用5无法交换元素,这让我感到困惑。我期望得到相反的结果,但是,我假设函数参数的一个条目将在另一个条目之前执行。从输出来看,情况似乎并非如此 那么,出于好奇,这种行为是被定义的吗?我如何理解事物执行的顺序?谢谢 #include <iostream> #include <vector> #include <alg

在函数调用的上下文中,
it++
++it
的行为的解释是什么?更具体地说,对于函数
iter\u swap
?下面代码中的调用2调用4似乎在交换元素,而调用3调用5无法交换元素,这让我感到困惑。我期望得到相反的结果,但是,我假设函数参数的一个条目将在另一个条目之前执行。从输出来看,情况似乎并非如此

那么,出于好奇,这种行为是被定义的吗?我如何理解事物执行的顺序?谢谢

#include <iostream>
#include <vector>
#include <algorithm>
int main(void) {
    vector<int> a;
    a.push_back(1);
    a.push_back(2);

    vector<int>::iterator it_a, it_b;
    it_a = a.begin();
    it_b = it_a + 1;

    cout << *it_a << " " << *it_b << endl;
    // call 1
    iter_swap(it_a, it_b);
    cout << *it_a << " " << *it_b << endl;
    // call 2
    iter_swap(it_a, it_a++);
    cout << *--it_a << " " << *it_b << endl;
    // call 3
    iter_swap(it_a, ++it_a);
    cout << *--it_a << " " << *it_b << endl;
    // call 4
    iter_swap(it_a++, it_a);
    cout << *--it_a << " " << *it_b << endl;
    // call 5
    iter_swap(++it_a, it_a);
    cout << *--it_a << " " << *it_b << endl;

    return 0;
}

大多数示例都没有定义行为(调用1是唯一的例外)。函数参数的求值是不排序的,这意味着它们的求值顺序是未指定的,因此在调用函数时,
运算符+++
是否对另一个参数产生了副作用是未定义的。使用不同的编译器,您可以得到不同的结果,并且两者都完全符合标准

附录:我相信,对语义的一些解释是正确的

在C++11之前,我会在这里讨论序列点,但是标准语言已经变得更加清晰,没有太多变化。因此,我将讨论顺序操作

通常,C++11中的操作在时间上是部分有序的。也就是说,两个操作(我们称之为O和P)可以排序,这样O在
P之前排序,O在P之后排序,或者O和P是不确定排序的,或者O和P是未排序的

前两个很简单:如果O在p之前排序,那么它的所有效应都必须在p被评估时发生;如果O在p之后排序,那么当O出现时,p的所有效应都出现了

至于另外两个:如果O和p的顺序不确定,那么要么O的所有效应出现在p被评估之前,要么p的所有效应出现在O被评估之前。如果它们没有顺序,这对所有人来说都是一个巨大的自由:O的一些效应可能出现在P的一些效应之前,同时P的一些效应可能出现在O的所有效应出现之前——实际上,对O和P的评估可能重叠

这必须从优化的角度来看待:优化编译器喜欢重新排列代码以使其运行得更快。排序方面的部分规范允许他们做更多的事情——也许O有一个中间结果,对P的评估很有用,诸如此类的事情。如果你考虑,例如,一个大的算术表达式,不难看出Lax序列如何帮助矢量化,并且在有限数量的寄存器的存在下。 那么,你的例子在哪里


在C++11的第1.9(15)节中,提到“与不同参数表达式相关的值计算和副作用是未排序的。
”,因此您在这里处于最深处,与龙共游。

参数的计算顺序没有指定,并且参数列表中没有序列点,所以你的函数调用会导致。更糟糕的是,我们不仅有未指定的行为,还有未定义的行为。请记住,向量迭代器可以是普通指针。
1 2
2 1
1 2
1 2
2 1
2 1