【问题标题】:how to find if std::deque holds given object?如何查找 std::deque 是否持有给定对象?
【发布时间】:2014-04-16 17:37:09
【问题描述】:

我有一个container<std::deque<T>> 和一个const T*ptr,我知道它们指向包含的deques 之一中的一个对象。现在,我想知道(1)它来自哪个deque,以及(2)它在那个中的索引。如何获取这些信息?

我知道我可以遍历所有对象,但应该有更快的解决方案,不是吗?

【问题讨论】:

  • 我不知道您是如何进入那个角落的,但最好的解决方案很可能是重构原始问题以避免这种情况。这里有几个危险信号,例如,deque 中间的插入或删除可以更改您的指针所指的对象(概念上使用 对象 作为保存您的值的对象期待)
  • @DavidRodríguez-dribeas 我使用deques 作为临时对象的线程本地分配器。我最后只emplace()他们,因此永远不会使任何以前的指针无效。
  • ...由于某种原因您不知道哪个线程分配了对象?这是否意味着不同的线程可能正在尝试解除分配/作用于对象,因此该对象实际上是 shared 而不是 thread-local(概念上)?如果您确实知道线程,那么您应该知道 deque 中的哪个持有该值,对吧?
  • 对象是线程本地分配和使用的,但在算法的另一个阶段,它们是共享的。他们的寿命与container<std::deque<T>> 一样长。 container 本质上是map<thread::id,std::deque<T>> 的(线程安全版本)。
  • 如果稍后不同的线程访问同一个对象,那么您不能认为deque 是线程本地的。考虑动态创建对象并传递指针的所有权。这样deque 的使用将由单个线程访问。否则,您将始终有多个线程访问相同的 deque 数据结构。

标签: c++ deque


【解决方案1】:

类似的东西(我还没有编译这个,但你明白了):

container<deque<T>> MyCont;
for( auto iter = MyCont.begin(); iter != MyCont.end(); ++iter )
{
  auto foundIter = find( *iter.begin(), *iter.end(), MyObject );
  if ( foundIter != *iter.end() )
  {
    dequeIndex = distance( *iter.begin(), foundIter );
    containerIndex = distance( MyCont.begin(), iter );
    break;
  }
}

【讨论】:

  • find 算法将找到具有相同的对象,而不是相同的对象(即不是具有给定地址的对象)。为此,您必须将std::find_if 与检查身份的谓词一起使用。除此之外,std::distance 算法采用两个迭代器,而不是一个值和一个迭代器 (*iter.begin()),并且您无需第二次调用 distance 通过跟踪外部循环中的计数(并且没有使用循环而不是 find...)
  • 那么,没有比遍历所有对象更快的解决方案了吗?
  • @Walter:如果您需要相同的对象,则不需要。除非你有更多的保证。不过,您可以存储指针而不是对象,从而允许您使用 std::map。
  • @DavidRodríguez-dribeas 我误读了代码。我认为 deque 是指针,并假设他正在寻找确切的对象而不是等效的对象。距离应该通过两个迭代器。你也是正确的,可以通过添加一个计数器来消除一个距离。
  • @qeadz: 嗯.. 我看错了代码,但无论如何它都是错误的。你的意思是做iter-&gt;begin()(或(*iter).begin(),而不是*iter.begin()。我读到*XXX.begin(),它取消了对begin()的调用结果,从而取消了一个迭代器。
【解决方案2】:

这是一个双重迭代的任务:

  1. 遍历容器
  2. 迭代当前元素(双端队列)并进行比较

#

template<typename container> std::pair<container::iterator_t, size_t> FindIndices(const container& c, const container::value_type* x) {
    for(auto a = c.begin(); a != c.end(); a++)
        for(auto b = a->begin(); b != a->end(); b++)
            if(&*b == x)
                return std::pair<container::iterator_t, size_t>(a, b-a->begin());
    return std::pair<container::iterator_t, size_t>(c.end(), -1);
}

如果您可以将 shared_pointers 或 unique_pointers 存储在容器中,则可以使用 std::map 来有效地检索索引,只要它们不改变。
如果只是队列没有改变,那么仍有一些节省的潜力。

【讨论】:

  • +1 表示前三行。最后一行是错误的,你不能使用 stored 对象的地址作为 map 中的 key,因为插入它需要 key,直到 才能获取插入元素的地址i>在它被插入之后。
  • 问题可能不是你在插入之后才得到地址,而是额外的插入会使它失效。不过效果一样,所以我删除了它。
  • 嗯,指向std::map 的指针和引用是稳定的(从插入到删除从不改变)
猜你喜欢
  • 1970-01-01
  • 2011-09-11
  • 2010-12-28
  • 1970-01-01
  • 2021-11-30
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多