递归迭代而不重新绑定引用

时间:2017-01-23 16:46:25

标签: c++ recursion

我有一个功能,减少,看起来像:

// bar is basically a linked list with extra stuff tagged on
void recurses(std::unique_ptr<bar> & P)
{
  bool ok = decide_if_this_P_is_acceptable(P);
  if (!ok)
  {
     recurses(P->getNextPtr());
     return;
  }
  // Now do lots more stuff involving the reference P and P.reset()
}

bar类公开了一个名为getNextPtr()的方法,该方法返回std::unique_ptr<bar>&,然后可以将其传递回recurses。

不幸的是,它为一些大输入吹了堆栈。我想将其转换为迭代,例如

void recurses(std::unique_ptr<bar> & P)
{
  bar * N = nullptr;
  for (;;)
  {
    bool ok = decide_if_this_P_is_acceptable(P);
    if (ok)
    {
       break;
    }
    P = P->getNextPtr();
  }
  // P is now OK
  // Now do lots more stuff involving the reference P and P.reset()
}

这当然拒绝编译,因为我们无法重新绑定引用(std::unique_ptr<bar> & P)。

如果让函数的其余部分改变哪个参考被认为是好的,我怎么能丢失递归呢?

1 个答案:

答案 0 :(得分:4)

最简单的解决方案是使用std::reference_wrapper而不是原始引用。它是可重新绑定的:

void recurses(std::reference_wrapper<std::unique_ptr<bar>>& P)
{
  bar * N = nullptr;
  for (;;)
  {
    bool ok = decide_if_this_P_is_acceptable(P);
    if (ok)
    {
       break;
    }
    P = P.get().getNextPtr();
  }
  // P is now OK
  // Now do lots more stuff involving the reference P and P.reset()
}

请注意.get()调用之前的其他.getNextPtr(),它首先访问基础引用。您必须在所有成员函数调用上执行此操作。

或者,您可以在内部使用指针:

void recurses(std::unique_ptr<bar>& R)
{
  std::unique_ptr<bar>* P = &R;

  bar * N = nullptr;
  for (;;)
  {
    bool ok = decide_if_this_P_is_acceptable(*P);
    if (ok)
    {
       break;
    }
    P = &P->getNextPtr();
  }
  // P is now OK
  // Now do lots more stuff involving the reference P and P.reset()
}