如何移动std :: unique_ptr<从一个STL容器到另一个? [英] how to move an std::unique_ptr<> from one STL container to another?

查看:118
本文介绍了如何移动std :: unique_ptr<从一个STL容器到另一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板容器 MyContainer< std :: unique_ptr< Foo>> 其中具有 std :: deque< T> std :: vector< T> 成员。

I have a template container MyContainer<std::unique_ptr<Foo>> which has a std::deque<T> and a std::vector<T> member.

内部方法 send_to_purgatory_if(谓词),我想查看 m_taskdq 中的所有项目并从 m_taskdq m_purgatory ,如果谓词的评估结果为真。

Inside method, send_to_purgatory_if( predicate ), I would like to look at all items in m_taskdq and move items from m_taskdq to m_purgatory, if the predicate evaluates to true.

我遇到了两个问题:


  • 我的迭代器 如果我从循环内部从m_taskdq中删除项目,它会被丢掉

  • 我担心 std的状态:: unique_ptr<> 如果我分两步进行操作(问题第1行和第2行-第2行,我认为 std :: unique_ptr<> 它指向的code> 是未定义的?)

  • my iterator it gets trashed if I remove items from m_taskdq from inside the loop
  • I am worried about the state of the std::unique_ptr<> if I do the move in two steps (problem lines 1 and 2 - by line 2, I think the std::unique_ptr<> pointed to by it is undefined?)

我应该如何解决此代码?

    template <typename T>
    class MyContainer
    {
      typedef std::function<bool(T&)>  PREDICATE;
    
      void send_to_purgatory_if( PREDICATE p )
      {
// bad code -------------------------------------
        for( auto it=m_taskdq.begin(); it!=m_taskdq.end(); ++it )
        {
          if ( p( *it ) )
          {
            m_purgatory.emplace_back( move( *it ));  // problem line 1
            m_taskdq.erase( it );                    // problem line 2
          }
        }
// end bad code ---------------------------------
      }
    
      std::deque<  T >  m_taskdq;                                                     
      std::vector< T >  m_purgatory;
    };


推荐答案

这确实是一个C ++ 98问题,关于移动语义的红鲱鱼。首先要问的是如何在C ++ 98中执行此操作:

This is really a C++98 question, with a red-herring concerning move semantics. The first thing to ask is how to do this in C++98:

std :: deque :: erase(iterator)返回一个 iterator ,该元素引用被删除元素之后的元素。因此,首先开始工作:

std::deque::erase(iterator) returns an iterator that refers to the element after the one erased. So get that working first:

 void send_to_purgatory_if( PREDICATE p )
  {
    for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
    {
      if ( p( *it ) )
      {
        m_purgatory.emplace_back(*it);
        it = m_taskdq.erase(it);
      }
      else
        ++it;
    }
  }

现在很容易使其与C一起使用++ 11移动语义:

And now it is easy to make it work with C++11 move semantics:

 void send_to_purgatory_if( PREDICATE p )
  {
    for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
    {
      if ( p( *it ) )
      {
        m_purgatory.emplace_back(std::move(*it));
        it = m_taskdq.erase(it);
      }
      else
        ++it;
    }
  }

unique_ptr taskdq 中移出的c $ c>在 emplace_back unique_ptr c $ c>,然后在下一行将其删除。没有伤害,没有犯规。

The unique_ptr moved from in taskdq becomes a null unique_ptr after the emplace_back, and then it gets erased in the next line. No harm, no foul.

当发生擦除时,从返回擦除在增加迭代器方面做得很好。当没有 擦除时,按顺序进行正常的迭代器增量。

When there is an erase, the return from the erase does a good job at incrementing the iterator. And when there is no erase, a normal iterator increment is in order.

这篇关于如何移动std :: unique_ptr&lt;从一个STL容器到另一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆