【问题标题】:I'm having trouble understanding how Post Increment (++), Pre Increment work together in an example [duplicate]我无法理解 Post Increment (++)、Pre Increment 在示例中如何协同工作 [重复]
【发布时间】:2021-03-20 15:18:18
【问题描述】:

我无法理解 Post Increment (++) 和 Pre Increment 在示例中如何协同工作。

x++ 表示变量加 1 但我对这个例子感到困惑:

using namespace std;
/ run this program using the console pauser or add your own getch, system("pause") or input loop */
int main() {
    int a;
    a=8;
    cout<<++a<<a++<<endl;
    cout<<a<<endl;
    return 0;
}

我假设这意味着首先增加 1,然后它将首先分配然后增加这意味着结果应该是 9 8 和 9 但是当我编译它时,我得到 10 8 和 10。我不明白.

【问题讨论】:

  • 你能看到像g(f(++a), a++)这样的函数调用的问题吗?
  • 如何将 8 递增两次得到 9?
  • 如果 a = 8: ++a => 使用 9 仍然是 9 a++ => 使用 8 并且仍然是 9
  • 另见here, here, here, here, here, here, here, here, here, @9 here, here, here, here

标签: c++ operators post-increment pre-increment


【解决方案1】:

您的困惑与前增量和后增量无关,而是与operator &lt;&lt; 的评估顺序有关。这方面有很多线程,这是一个很好的恕我直言:SO discussion about evaluation order

总结是:

  • 在 C++17 之前,如果有 std::cout &lt;&lt; f(a) &lt;&lt; g(a) &lt;&lt; std::endl; 等表达式,则未指定求值顺序(f 优先或g 优先)。

当我们看一下上面的表达的意思时,这就变得更清楚了。对于重载的operator&lt;&lt;,它实际上变成了

operator<<(operator<<(std::cout, f(a)), g(a));
so: 
function  (<--------- arg 1 --------->,<arg2>)

在这种情况下,评估是无序的,也没有定义是先评估arg1还是arg2。

  • 在 C++17 中,顺序是从左到右指定的。

来自[n4659] §8.2.2 : 5

如果使用运算符表示法调用运算符函数,则参数计算将按照内置运算符的指定顺序进行。

我对此解释如下:即使操作符被重载,如果它被称为操作符(即std::cout &lt;&lt; f(a) &lt;&lt; g(a) &lt;&lt; std::endl;),它也会被有效地评估为

std::cout.operator<<(f(a)).operator<<(g(a)).operator<<(std::endl);

但是,如果调用是明确的

operator<<(operator<<(std::cout, f(a)), g(a));

会被当作函数调用处理,仍然没有指定顺序。

  • 为安全起见,最好将打印/评估拆分为单独的语句(即用; 分隔),除非您有充分的理由不这样做(并且非常了解细节),尤其是因为不同的操作员行为不同(例如,+ 在 C++17 之后保持未排序)。

【讨论】:

  • 或者,也许投反对票的人只是对您在两天内回答这个问题的第 10 个版本表示异议。在我看来,这不是否决答案的好理由。
  • @Bathsheba 感谢您的反馈!如果fg 返回int,它们将被链接起来,而不是嵌套,对吧?因为std::cout &lt;&lt; f(a); == std::cout.operator(f(a));。对于自定义类型,情况会有所不同。
  • 是的,可能是真的,我只是注意到还有多少人,可以删除我的。
  • @Bathsheba:完成。老实说,现在我对它进行了更多研究,我不清楚为什么 int 的情况下没有指定顺序。毕竟,我希望 std::cout &lt;&lt; int(2) &lt;&lt; int(3); 在 C++17 之前就等于 std::cout.operator(int(2)).operator(int(3));。对于非内置类型,情况就不同了。
猜你喜欢
  • 1970-01-01
  • 2021-01-14
  • 2022-01-29
  • 2017-09-15
  • 2017-05-03
  • 1970-01-01
  • 2012-07-14
  • 2022-11-07
  • 2018-09-13
相关资源
最近更新 更多