C++ 当将迭代器作为参数传递并在尾部位置递归时,为什么后缀失败,前缀工作正常?

C++ 当将迭代器作为参数传递并在尾部位置递归时,为什么后缀失败,前缀工作正常?,c++,recursion,prefix,postfix,C++,Recursion,Prefix,Postfix,我偶然遇到这个问题 我原以为谷歌一定能解决这个问题,但在搜索了多个关键词后,我仍然找不到答案,这让我很困惑 当我在尾部位置使用前缀时,代码工作正常: template<class ContinerIterator, class F> constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f) { switch (IteratorBegin == IteratorEn

我偶然遇到这个问题

我原以为谷歌一定能解决这个问题,但在搜索了多个关键词后,我仍然找不到答案,这让我很困惑

当我在尾部位置使用前缀时,代码工作正常:

template<class ContinerIterator, class F>
constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f)
{
    switch (IteratorBegin == IteratorEnd)
    {
    case true: return;
    case false: f(*IteratorBegin);
    }
    return fun(++IteratorBegin, IteratorEnd, f);
}
int main()
{
    std::vector<int> a = { 1, 2, 3, 4 };
    fun(std::begin(a), std::end(a), [](auto &a)->auto{a *= 2; });
    for (auto v : a)
    {
        std::cout << v << std::endl;
    }
    return 0;
}
我在MSVC上试过,G++,叮当声,都失败了。 以下是gcc的错误列表:

分段故障(堆芯转储)

这是克朗的:

发生错误(超时)。请稍后再试

前缀大小写:

return fun(++IteratorBegin, IteratorEnd, f);
表示,首先将
IteratorBegin
递增1,然后调用函数
fun
。之后,返回

另一方面,后缀的情况是:

return fun(IteratorBegin++, IteratorEnd, f);
首先调用
fun()
,然后递增迭代器,然后返回


这意味着总是使用非递增迭代器调用
fun()

在尾部调用中使用后缀递增时,递归调用不会获得迭代器的递增值。它在应用增量之前获取迭代器的值。因此,递归是无限的。这会导致堆栈溢出。

此语句

return fun(IteratorBegin++, IteratorEnd, f);
除了一些例外情况,可以认为

fun(IteratorBegin, IteratorEnd, f);
++IteratorBegin;
return;
因此,始终使用相同的值
IteratorBegin
调用该函数

从C++标准(5.2.6增量和递减)

1后缀++表达式的值是其操作数的值。[ 注:获得的值是原始值的副本-结束注 ]

考虑下面的简单程序

#include <iostream>

void f(int x)
{
    std::cout << "Inside f( x ): x = " << x << std::endl;
}

int main()
{
    int x = 0;

    std::cout << "Before f( x ): x = " << x << std::endl;
    f(x++);
    std::cout << "After  f( x ): x = " << x << std::endl;

    return 0;
}
#include <iostream>

int x = 0;

void f(int x)
{
    std::cout << "Local (parameter) x = " << x << std::endl;
    std::cout << "Global variable ::x = " << ::x << std::endl;
}

int main()
{
    f(x++);

    return 0;
}
也可以考虑以下简单的程序

#include <iostream>

void f(int x)
{
    std::cout << "Inside f( x ): x = " << x << std::endl;
}

int main()
{
    int x = 0;

    std::cout << "Before f( x ): x = " << x << std::endl;
    f(x++);
    std::cout << "After  f( x ): x = " << x << std::endl;

    return 0;
}
#include <iostream>

int x = 0;

void f(int x)
{
    std::cout << "Local (parameter) x = " << x << std::endl;
    std::cout << "Global variable ::x = " << ::x << std::endl;
}

int main()
{
    f(x++);

    return 0;
}

听起来您可能需要学习如何使用调试器逐步完成代码。有了一个好的调试器,您可以逐行执行您的程序,并查看它偏离预期的地方。这是一个必要的工具,如果你要做任何编程。进一步阅读:如果postfix是根据通常的语义实现的,这应该是显而易见的。很少看到switch语句以这种方式使用。我会使用一个普通的if/else来完成这个任务。@NathanOliver我已经试过调试,比如“步进函数”,然后发现迭代器beginner不断增加。@NathanOliver谢谢!我很不小心,没有注意到迭代器本身仍然是相同的地址,不同的是它的值。也许这是熬夜很多天的结果,哈哈。
Local (parameter) x = 0
Global variable ::x = 1