【问题标题】:Join and re-split two std::list's without allocation加入并重新拆分两个 std::list 而不分配
【发布时间】:2011-10-06 22:52:59
【问题描述】:

我想做以下事情:

  1. 加入两个std::lists(l1l2
  2. 将组合列表传递给函数
  3. 恢复原来的两个列表

这一切都应该在不分配新内存的情况下发生。

首先我想用splice() 尝试这个,但后来我读到移动项目的迭代器将被splice() 失效。 但是,然后,我读了这个 SO 答案:splice() on std::list and iterator invalidation 并决定尝试一下:

iterator temp = l2.begin();
l1.splice(l1.end(), l2);
my_function(l1);
l2.splice(l2.end(), l1, temp, l1.end());

这在许多情况下都有效,但如果 l2 最初为空,则无效(因为 temp 没有指向任何有意义的内容)。

当然,我可以检查 l2.size() > 0,但对我来说,这一切似乎有点太简单了。

有人知道我最初的问题的更好/更清洁的解决方案吗?

【问题讨论】:

  • 如果 my_function 实际上是“你的”函数,你可以让它有一个开始和结束的迭代器......然后创建一个通用的聚合迭代器类来处理跨多个集合的逻辑。 ..?
  • @HostileFork:感谢您的评论,我想过这个问题,但是对于我手头的任务来说,这样一个花哨的迭代器似乎有点太费力了。但真正的缺点是我总是不得不使用 fancy iterator,即使我只有一个简单的列表。我没有提到这一点,但我希望能够将 my_function() 有时用于单个列表,而有时用于组合列表,这不是编译时决定。跨度>
  • 我不明白您所说的“不是编译时决定”是什么意思,但无论如何,fancy iterator 可以非常简单地简化为单个列表案例...如果只有一个,它的开始和结束方法将简单地返回包含列表的开始和结束迭代器的包装版本。几乎没有任何性能受到影响。你也可以重载my_function
  • 很抱歉给您带来了困惑。基本上我的意思是 my_function 不能是模板函数。此函数在某些工作线程中被重复调用,并且每次都必须是完全相同的函数(无重载)。所以我只能有一种迭代器类型,它必须是fancy iterator。无论如何,我确信它会起作用,但我发现列表操作更易于实现且更易于理解。

标签: c++ list stl iterator


【解决方案1】:

你可以改变逻辑来保持一个有效的迭代器:

auto temp = l2.begin();

l2.splice(temp, l1);  // "L2 = L1 + L2"

my_function(l2);

l1.splice(l1.end(), l2, l2.begin(), temp);  // restores both l1 and l2

【讨论】:

  • 哇,这么小的变化就大不一样了!现在完美运行!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 2022-01-15
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多